Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# Windows Forms
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
Suppir
24 / 24 / 10
Регистрация: 08.08.2011
Сообщений: 1,157
#1

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

18.02.2015, 21:39. Просмотров 995. Ответов 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
Ответы с готовыми решениями:

Как правильно дождаться завершения потока?
Здравствуйте у меня возник вопрос как дождаться завершения потока метод...

Как очистить память после завершения потока?
Как очистить память после завершения потока? Каждые 1000 мс поток запускается...

Ожидание завершения потока
private void button1_Click(object sender, EventArgs e) { ...

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

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

10
insite2012
Модератор
Эксперт .NET
4849 / 3804 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 2
18.02.2015, 22:05 #2
Цитата Сообщение от Suppir Посмотреть сообщение
Как это сделать?
А почему не используете асинхронный метод?
https://msdn.microsoft.com/ru-ru/library/ms144196(v=vs.110).aspx
0
Suppir
24 / 24 / 10
Регистрация: 08.08.2011
Сообщений: 1,157
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
4849 / 3804 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 2
18.02.2015, 22:11 #4
Цитата Сообщение от Suppir Посмотреть сообщение
Нашел такой способ
По правде говоря, это не способ, это костыль. Выше я дал ссылку на асинхронный метод. Зачем изобретать велосипед?
0
Suppir
24 / 24 / 10
Регистрация: 08.08.2011
Сообщений: 1,157
18.02.2015, 22:11  [ТС] #5
insite2012, ну, мне нужно много файлов качать, при этом - обновлять интерфейс. Чтобы определить, что файл скачался, потребуется использовать обработчик события DownloadFileComplete. Но при этом не будет понятно, какой же именно файл скачался.
0
insite2012
Модератор
Эксперт .NET
4849 / 3804 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 2
18.02.2015, 22:14 #6
Цитата Сообщение от Suppir Посмотреть сообщение
При этом не будет понятно, какой же именно файл скачался.
С чего бы? Создайте список, в него вносите имена файлов.
Вы сами себе усложняете работу, ятд)))
0
Suppir
24 / 24 / 10
Регистрация: 08.08.2011
Сообщений: 1,157
18.02.2015, 22:15  [ТС] #7
Цитата Сообщение от insite2012 Посмотреть сообщение
Создайте список, в него вносите имена файлов.
А можете на простом примере показать?
0
insite2012
Модератор
Эксперт .NET
4849 / 3804 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 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 / 10
Регистрация: 08.08.2011
Сообщений: 1,157
18.02.2015, 22:45  [ТС] #9
Понятно, спасибо, попробую.
0
kenny69
burning1ife
1377 / 1203 / 283
Регистрация: 21.09.2008
Сообщений: 3,364
Записей в блоге: 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
6116 / 3668 / 1391
Регистрация: 11.01.2015
Сообщений: 4,834
Записей в блоге: 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

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

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

Бинарная сериализация - Error - Конец потока обнаружен до завершения разбора
Делаю сетевую игру пинг-понг(вот похожая игра -...


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

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

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