为什么HttpClient.PostAsyc().结果可以在同步方法中使用
本文关键字:同步方法 PostAsyc HttpClient 结果 为什么 | 更新日期: 2023-09-27 18:04:20
据我所知,调用async
方法返回的Task
的Result
属性会导致Winform应用程序死锁。例如,下面的代码可能导致死锁:
public void Button_Click(object sender, EventArgs e)
{
var r = MyAsyncFunc().Result;
}
但是呼叫HttpClient.PostAsync().Result
似乎没有问题。有什么魔力吗?
在大多数情况下,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();