2016-08-27 5 views
2

私が知る限り、のResultプロパティを呼び出すと、asyncメソッドが返され、Winformアプリケーションでデッドロックが発生します。例えば、以下のコードは、デッドロックを引き起こす可能性があります:なぜHttpClient.PostAsyc()。結果は、同期メソッドで使用できますか?

public void Button_Click(object sender, EventArgs e) 
{ 
    var r = MyAsyncFunc().Result; 
} 

しかしHttpClient.PostAsync().Resultを呼び出すと、何の問題もないようです。魔法は何ですか?

答えて

0

ほとんどのシナリオでは、UIスレッドはシングルスレッドです。 UIスレッドから呼び出されたもの、またはUIスレッドに行くものはすべて呼び出される必要があります。したがって、

var myResult = Http.Client.PostAsync()。結果; //は正常ですが、

TextBox_t.Text = Http.Client.PostAsync()。結果; //それほど良くない。

非同期操作の結果をUIスレッドに戻す必要があります。

0

UIを更新することができるwinformsアプリケーション内にはスレッドが1つしかなく、バックグラウンドスレッドからUIを更新することはできず、UIをロックせずにバックグラウンドスレッドを待つことはできません。

以下は、バックグラウンドプロセスを使用してファイルをダウンロードし、バックグラウンドワーカーを使用して進行状況バーを更新した例です。私はWebClientを使用していました。

BackgroundWorker bw = new BackgroundWorker(); 
    WebClient webClient = new WebClient(); 
    bw.WorkerReportsProgress = true; 

    //setup delegate for download progress changed. - runs in bw thread 
    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(delegate(object sender, DownloadProgressChangedEventArgs e) 
    { 
     // do something here every time the background worker is updated e.g. update download progress percentage ready to update progress bar in UI. 
     double bytesIn = double.Parse(e.BytesReceived.ToString()); 
     double totalBytes = double.Parse(e.TotalBytesToReceive.ToString()); 
     double percentage = bytesIn/totalBytes * 100; 
     int progress = int.Parse(Math.Truncate(percentage).ToString()); 
     bw.ReportProgress(progress); 
    }); 

    //setup delegate for download backgroub worker progress changed. - runs in UI thread 
    bw.ProgressChanged += new ProgressChangedEventHandler(delegate(object o, ProgressChangedEventArgs e) 
    { 
     // this thread has access to UI, e.g. take variable from above and set it in UI. 
     progressBar.Value = e.ProgressPercentage; 
    }); 

    //setup delegate for download completion. - runs in bw thread 
    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(delegate(object sender, AsyncCompletedEventArgs e) 
    { 
     // do something here when download finishes 
    }); 

    //setup delegate for backgroud worker finished. - runs in UI thread 
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs e) 
    { 
     // do something here than needs to update the UI. 
    }); 

    //MAIN CODE BLOCK for backgroud worker 
    bw.DoWork += new DoWorkEventHandler(delegate(object o, DoWorkEventArgs args) 
    { 
     // execute the main code here than needs to run in background. e.g. start download. 
     // this is where you would start the download in webClient. e.g. webClient.DownloadString("some url here"); 
    }); 

    bw.RunWorkerAsync(); 
関連する問題