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

时间:2016-08-27 05:31:36

标签: c# async-await

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

async

但是调用public void Button_Click(object sender, EventArgs e) { var r = MyAsyncFunc().Result; } 似乎没问题。什么是魔术?

2 个答案:

答案 0 :(得分:0)

在大多数情况下,UI线程是单线程的。应该调用从UI线程调用的任何内容。所以,

var myResult = Http.Client.PostAsync()。结果; //很好,但是

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

您必须通过异步操作调用UI线程中的任何结果。

答案 1 :(得分:0)

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();