0

C++/CLI で Windows フォーム アプリケーションを使用するときに、ちょっとしたイライラする問題があります。

問題は、WebClient インスタンスを使用して Web サーバーからファイルをダウンロードする必要があることです。通常、私は 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 ++に「翻訳」しました。しかし、うまくいきません...

4

1 に答える 1

2

待つことができず、デッドロックが発生します。DownloadFileCompleted() メソッドは、メイン スレッドがアイドル状態になり、ディスパッチャ ループに再び入るまで実行できません。しかし、それはアイドル状態ではなく、WaitOne() 呼び出しでスタックしています。そのため、メソッドを実行できず、MRE を設定できません。その結果、WaitOne() が完了しません。あなたのプログラムが決して回復できない致命的な抱擁。標準的なスレッド化バグの 1 つです。

待つ理由は明らかではありません。投稿された WaitOne() 呼び出しにはまったく意味がありません。単に削除するだけで、すべて正常に機能します。実際のプログラムでは、実際にはそのコードの後に​​いくつかのコードがある可能性があります。そのコードを DownloadFileCompleted() メソッドに移動する必要があります。

ここでは、UI を表示するスレッドの一般的なプログラミング ルールが適用されます。それは眠ることもブロックすることもできない。これを行うと、UI が応答しなくなり、デッドロックの可能性が大幅に高まります。UI はイベント ドリブンであり、たとえばユーザーがマウスを動かしたりキーを押したりすることによってイベントがトリガーされます。イベントが発生したときに実行されるコードは、スレッドが他に何もしていないときにのみ実行できます。ダウンロードの完了もイベントとして通知されます。

于 2015-03-28T11:24:07.260 に答える