Форум программистов, компьютерный форум, киберфорум
Наши страницы

C# Windows Forms

Войти
Регистрация
Восстановить пароль
 
Suppir
24 / 24 / 3
Регистрация: 08.08.2011
Сообщений: 1,155
#1

Как ожидать завершения потока, чтобы не подвисал интерфейс - C#

18.02.2015, 21:39. Просмотров 941. Ответов 10
Метки нет (Все метки)

Добрый день!

Нужно скачивать файлы из интернета. Хочу, чтобы во время скачивания не подвисал интерфейс. Пишу:

C#
1
2
3
4
5
6
7
Thread ThreadDownload = new System.Threading.Thread(delegate() {
    WebClient myWebClient = new WebClient();
    myWebClient.DownloadFile(pdf, "документы/" + filename);
});
ThreadDownload.Start();
 
ThreadDownload.Join();
Для ожидания завершения треда служит строчка:
C#
1
ThreadDownload.Join();
Проблеммка в том, что при этом интерфейс программы подвисает. А мне нужно сделать так, чтобы интерфейс делал Application.DoEvents() в момент, пока файлы скачиваются. Как это сделать?
По некоторым причинам скачивание через backgroundworker для моего случая не подходит.


P.S. Прошу изменить название темы: "Как ожидать завершения потока, чтобы не подвисал интерфейс"
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.02.2015, 21:39
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как ожидать завершения потока, чтобы не подвисал интерфейс (C#):

Как правильно дождаться завершения потока? - C#
Здравствуйте у меня возник вопрос как дождаться завершения потока метод Thread.join(); тормозит форму да и всу программу А мне нужно чтоб...

Ожидание завершения потока - C#
private void button1_Click(object sender, EventArgs e) { System.Threading.Thread MyThread1 = ...

Как сделать, чтобы вывод данных в форму происходил до завершения программы? - C#
Как сделать, чтобы вывод данных в форму происходил до завершения программы? Есть маленькая програмка на C#, где после авторизации в...

Ждать завершения потока (без зависания формы) - C#
Здравствуйте товарищи! Столкнулся с такой вот проблемой. Пишу программу, которая запускает через cmd.exe некие команды. Форма...

Десериализация. Конец потока обнаружен до завершения разбора - C#
При десереализации возникает следующая ошибка: Объект, не помечен, как сериализуемый. Конец потока обнаруен до завершения разбора. На...

Закрытие потока для корректного завершения работы приложения - C#
Запускаю получение видео при запуске формы public MainForm() { InitializeComponent(); MJPEGStream...

10
insite2012
Модератор
Эксперт .NET
4772 / 3731 / 902
Регистрация: 12.10.2013
Сообщений: 10,946
Записей в блоге: 2
18.02.2015, 22:05 #2
Цитата Сообщение от Suppir Посмотреть сообщение
Как это сделать?
А почему не используете асинхронный метод?
https://msdn.microsoft.com/ru-ru/library/ms144196(v=vs.110).aspx
0
Suppir
24 / 24 / 3
Регистрация: 08.08.2011
Сообщений: 1,155
18.02.2015, 22:09  [ТС] #3
Нашел такой способ:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Thread ThreadDownload = new System.Threading.Thread(delegate() {
    WebClient myWebClient = new WebClient();
    myWebClient.DownloadFile(pdf, "документы/" + filename);
});
ThreadDownload.Start();
 
Stopwatch sw = new Stopwatch();
sw.Start();
 
bool error = false;
while (ThreadDownload.IsAlive)
{
    Application.DoEvents();
    if (sw.ElapsedMilliseconds > fileTimeout)
    {
        ThreadDownload.Abort();
        error = true;
    }
 
}
То есть скачивается в другом потоке. Если поток живой, то делается Application.DoEvents(). Если период ожидания истек, тогда поток принудительно прерывается. Вроде, работает.
0
insite2012
Модератор
Эксперт .NET
4772 / 3731 / 902
Регистрация: 12.10.2013
Сообщений: 10,946
Записей в блоге: 2
18.02.2015, 22:11 #4
Цитата Сообщение от Suppir Посмотреть сообщение
Нашел такой способ
По правде говоря, это не способ, это костыль. Выше я дал ссылку на асинхронный метод. Зачем изобретать велосипед?
0
Suppir
24 / 24 / 3
Регистрация: 08.08.2011
Сообщений: 1,155
18.02.2015, 22:11  [ТС] #5
insite2012, ну, мне нужно много файлов качать, при этом - обновлять интерфейс. Чтобы определить, что файл скачался, потребуется использовать обработчик события DownloadFileComplete. Но при этом не будет понятно, какой же именно файл скачался.
0
insite2012
Модератор
Эксперт .NET
4772 / 3731 / 902
Регистрация: 12.10.2013
Сообщений: 10,946
Записей в блоге: 2
18.02.2015, 22:14 #6
Цитата Сообщение от Suppir Посмотреть сообщение
При этом не будет понятно, какой же именно файл скачался.
С чего бы? Создайте список, в него вносите имена файлов.
Вы сами себе усложняете работу, ятд)))
0
Suppir
24 / 24 / 3
Регистрация: 08.08.2011
Сообщений: 1,155
18.02.2015, 22:15  [ТС] #7
Цитата Сообщение от insite2012 Посмотреть сообщение
Создайте список, в него вносите имена файлов.
А можете на простом примере показать?
0
insite2012
Модератор
Эксперт .NET
4772 / 3731 / 902
Регистрация: 12.10.2013
Сообщений: 10,946
Записей в блоге: 2
18.02.2015, 22:40 #8
Цитата Сообщение от Suppir Посмотреть сообщение
можете на простом примере показать?
На совсем простом врд ли, адресов откуда скачивать у меня нет, и придумывать их не хочется.
Вот, набросал по быстрому, но поскольку адресов нет, в работе не проверял. Но логика, думаю, там понятна.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.ComponentModel;
 
namespace WebClient_Download {
    class Program {
        static void Main(string[] args) {
            
        }
    }
    class WebDownloader {
        private string[] fileNames;
        private string[] addresses;
        private EventWaitHandle wh = new AutoResetEvent(false);
        private WebClient client;
        private List<string> downloadedFiles = new List<string>();
 
        public List<string> DownloadedFiles {
            get { return downloadedFiles; }
            set { downloadedFiles = value; }
        }
        public WebDownloader(string[] names, string[] addr) {
            fileNames = names;
            addresses = addr;
            client = new WebClient();
            client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
        }
 
        void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) {
            downloadedFiles.Add(e.UserState.ToString());
            wh.Set();
        }
        public void StartDownload(){
            Task.Factory.StartNew(() => {
                for (int i = 0; i < addresses.Length; i++) {
                    client.DownloadFileAsync(new Uri(addresses[i]), fileNames[i], fileNames[i]);
                    wh.WaitOne();
                }
            });
        }
    }
}
1
Suppir
24 / 24 / 3
Регистрация: 08.08.2011
Сообщений: 1,155
18.02.2015, 22:45  [ТС] #9
Понятно, спасибо, попробую.
0
kenny69
burning1ife
1370 / 1197 / 171
Регистрация: 21.09.2008
Сообщений: 3,356
Записей в блоге: 9
19.02.2015, 09:41 #10
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  private async Task DownloadAsync(string uri, string filename)
        {
            try
            {
                using (var webClient = new WebClient())
                {
                    webClient.Credentials = CredentialCache.DefaultNetworkCredentials;
                    await webClient.DownloadFileTaskAsync(new Uri(uri), filename);
                }
            }
            catch (Exception)
            {
                //error!
            }
        }
Использовать вот так:
C#
1
2
3
4
5
 async Task DownloadAllAsync(List<string> urls)
        {
            await Task.WhenAll(urls.Select(uri => DownloadAsync(uri, "filename.txt")));
            //здесь можно сделать сообщение, что загрузка завершилась
        }
Добавлено через 3 минуты
вместо "filename.txt" можете передавать свой путь к файлу.
1
Storm23
Эксперт .NETАвтор FAQ
5728 / 3463 / 1056
Регистрация: 11.01.2015
Сообщений: 4,587
Записей в блоге: 31
19.02.2015, 10:39 #11
insite2012,
Цитата Сообщение от insite2012 Посмотреть сообщение
downloadedFiles.Add(e.UserState.ToString());
Здесь бы lock не помешал.
0
19.02.2015, 10:39
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.02.2015, 10:39
Привет! Вот еще темы с ответами:

Бинарная сериализация - Error - Конец потока обнаружен до завершения разбора - C#
Делаю сетевую игру пинг-понг(вот похожая игра - http://channel9.msdn.com/coding4fun/articles/Upgrade-Your-Game-TinyTennis-C). Данные о игре...

Как сделать так, чтобы метод вызванный из нового потока выполнялся в основном - C#
Вот есть код, специально всё скопировал в новый проект и упростил, чтобы была только идея понятна и компилировалось. Как сделать так, чтобы...

Зависает интерфейс при выполнении отдельного потока - C#
Как сделать так чтобы при выполнении потока не зависалось GUI? Вот небольшой код: using System; using...

Ожидать завершения стороннего процесса - Visual Basic .NET
здравствуйте. задача: 1. запустить консольную утилиту с определёнными параметрами ком. строки и перенаправить её вывод в файл 2....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru