为什么HttpClient.PostAsyc().结果可以在同步方法中使用

本文关键字:同步方法 PostAsyc HttpClient 结果 为什么 | 更新日期: 2023-09-27 18:04:20

据我所知,调用async方法返回的TaskResult属性会导致Winform应用程序死锁。例如,下面的代码可能导致死锁:

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

但是呼叫HttpClient.PostAsync().Result似乎没有问题。有什么魔力吗?

为什么HttpClient.PostAsyc().结果可以在同步方法中使用

在大多数情况下,UI线程是单线程的。任何从UI线程调用或到UI线程的东西都应该被调用。

var myResult = Http.Client.PostAsync().Result;//可以,但是

TextBox_t。Text = Http.Client.PostAsync().Result;//不太好。

你必须调用回UI线程从异步操作的任何结果。

在winforms应用程序中只有一个线程可以更新UI,你不能从后台线程更新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();