У меня есть небольшая, но разочаровывающая проблема в моем C ++ / CLI с приложением форм Windows.
Так что проблема в том, что мне нужно скачать файл с веб-сервера с помощью istance WebClient. Обычно я использую DownloadFile, а не DownoadFileAsyn, но если я хочу показать индикатор выполнения, показывающий ход загрузки файла, я ДОЛЖЕН использовать DownloadFileAsyn. Так как же мне дождаться окончания процесса загрузки?
Код является:
ref class Example{
private:
static System::Threading::ManualResetEvent^ mre = gcnew System::Threading::ManualResetEvent(false);
public:
void Download();
void DownloadFileCompleted(Object^ sender, System::ComponentModel::AsyncCompletedEventArgs^ e);
};
void Example::Download(){
WebClient^ request = gcnew WebClient;
request->Credentials = gcnew NetworkCredential("anonymous", "anonymous");
request->DownloadFileCompleted += gcnew System::ComponentModel::AsyncCompletedEventHandler(this,&FileCrypt::DownloadFileCompleted);
request->DownloadFileAsync(gcnew Uri("ftp://ftp...."+remote_path),remote_file,mre);
mre->WaitOne();/*
BLOCK OF INSTRUCTIONS THAT I WANT TO RUN AFTER THE FILE DOWNLOAD IS COMPLETED
*/
}
void Example::DownloadFileCompleted(Object^ sender, System::ComponentModel::AsyncCompletedEventArgs^ e){
MessageBox::Show("COMPLETED");
mre->Set();
}
Поэтому, когда загрузка завершена, программа перестает работать и не выполняет блок вышеописанных инструкций после инструкции mre-> WaitOne ().
DownloadFileCompleted () не выполняется, фактически отображается даже окно сообщения.
Есть идеи? Я искал для этой проблемы, и многие люди имели это, но только в C #. И я только что «перевел» решение с c # на c ++. Но это не работает …
Вы не можете ждать, что вызывает тупик. Метод DownloadFileCompleted () не может быть запущен до тех пор, пока ваш основной поток не перейдет в режим ожидания и не войдет в цикл диспетчера. Но он не простаивает, он застревает в вызове WaitOne (). Таким образом, метод не может быть запущен и MRE не может быть установлен. Что в свою очередь приводит к тому, что WaitOne () никогда не завершается. Смертельное объятие, от которого ваша программа никогда не сможет восстановиться. Одна из стандартных ошибок при работе с потоками.
Не понятно Зачем вы ждете, просто нет никакого смысла в вызове WaitOne () вообще, как опубликовано. Вы можете просто удалить его, и все работает отлично. Возможно, после этого в вашей реальной программе есть какой-то код, вы должны переместить этот код в метод DownloadFileCompleted ().
Общее правило программирования для потоков, отображающих пользовательский интерфейс, применяется здесь. Он никогда не может спать и никогда не может блокировать. Это делает пользовательский интерфейс невосприимчивым и значительно увеличивает шансы на тупик. Пользовательский интерфейс управляется событиями, события, инициируемые, например, движением мыши или нажатием клавиши. Код, который запускается при возникновении события, может выполняться только тогда, когда поток ничего не делает. Завершение загрузки также сигнализируется как событие.