等待 DownloadFileAsync 与 ManualResetEvent c++/cli

Waiting DownloadFileAsync with ManualResetEvent c++/cli

我在使用 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();
}

所以当下载完成后,程序停止 运行ning 并且它不会 运行 在 mre->WaitOne() 指令之后写入上面的指令块。 DownloadFileCompleted() 未执行,实际上甚至显示了消息框。

有什么想法吗?我已经搜索过这个问题,很多人都遇到过,但仅限于 c#。我刚刚 "translated" 从 c# 到 c++ 的解决方案。但是没用...

你不能等待,那会导致死锁。 DownloadFileCompleted() 方法无法 运行 直到您的主线程空闲并重新进入调度程序循环。但它并没有闲置,而是卡在了 WaitOne() 调用中。所以方法不能运行,MRE也不能设置。这反过来又导致 WaitOne() 永远无法完成。一个你的程序永远无法恢复的致命拥抱。标准线程错误之一。

不清楚您为什么等待,正如所发布的那样,WaitOne() 调用根本没有意义。您可以简单地删除它,一切正常。也许在您的实际程序中实际上在它之后有一些代码,您必须将该代码移动到 DownloadFileCompleted() 方法中。

显示 UI 的线程的一般编程规则适用于此处。它永远不会休眠,也永远不会阻塞。这样做会使 UI 无响应并显着增加死锁的可能性。 UI 是事件驱动的,例如用户移动鼠标或按键时触发的事件。当事件被触发时 运行s 的代码只能在线程没有做任何其他事情时 运行 。下载完成也作为事件发出信号。