我在使用 Windows 窗体应用程序的 C++/CLI 中遇到了一个小但令人沮丧的问题。
所以问题是我必须使用 WebClient istance 从网络服务器下载文件。通常我使用 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();
}
因此当下载完成后,程序停止运行并且它不会运行上面编写的指令 block ,在 mre->WaitOne() 指令之后。 DownloadFileCompleted() 未执行,实际上甚至显示了消息框。
有什么想法吗?我已经搜索过这个问题,很多人都遇到过,但仅限于 c#。我刚刚将解决方案从 C# 翻译成 C++。但它不起作用...
最佳答案
你不能等待,这会导致死锁。 DownloadFileCompleted() 方法无法运行,直到您的主线程空闲并重新进入调度程序循环。但它并没有闲置,而是卡在了 WaitOne() 调用中。因此该方法无法运行,无法设置 MRE。这反过来又导致 WaitOne() 永远无法完成。一个你的程序永远无法恢复的致命拥抱。标准线程错误之一。
不清楚为什么您要等待,正如发布的那样,WaitOne() 调用根本没有意义。您可以简单地删除它,一切正常。也许在您的实际程序中实际上在它之后有一些代码,您必须将该代码移到 DownloadFileCompleted() 方法中。
此处适用显示 UI 的线程的一般编程规则。它永远不会休眠,也永远不会阻塞。这样做会使 UI 无响应并显着增加死锁的可能性。 UI 是事件驱动的,例如用户移动鼠标或按下某个键时触发的事件。触发事件时运行的代码只能在线程未执行任何其他操作时运行。下载完成也作为事件发出信号。
关于c++ - 等待 DownloadFileAsync 与 ManualResetEvent c++/cli,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29316244/