【发布时间】:2016-05-05 00:17:44
【问题描述】:
我不知道是我做错了什么还是我在 Async 库中发现了一个错误,但是当我使用 continueWith() 返回到同步上下文后,我在运行一些异步代码时发现了一个问题。
更新:代码现在运行
using System;
using System.ComponentModel;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
internal static class Program
{
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MainFrameController controller = new MainFrameController(this);
//First async call without continueWith
controller.DoWork();
//Second async call with continueWith
controller.DoAsyncWork();
}
public void Callback(Task<HttpResponseMessage> task)
{
Console.Write(task.Result); //IT WORKS
MainFrameController controller =
new MainFrameController(this);
//third async call
controller.DoWork(); //IT WILL DEADLOCK, since ConfigureAwait(false) in HttpClient DOESN'T change context
}
}
internal class MainFrameController
{
private readonly Form1 form;
public MainFrameController(Form1 form)
{
this.form = form;
}
public void DoAsyncWork()
{
Task<HttpResponseMessage> task = Task<HttpResponseMessage>.Factory.StartNew(() => DoWork());
CallbackWithAsyncResult(task);
}
private void CallbackWithAsyncResult(Task<HttpResponseMessage> asyncPrerequisiteCheck)
{
asyncPrerequisiteCheck.ContinueWith(task =>
form.Callback(task),
TaskScheduler.FromCurrentSynchronizationContext());
}
public HttpResponseMessage DoWork()
{
MyHttpClient myClient = new MyHttpClient();
return myClient.RunAsyncGet().Result;
}
}
internal class MyHttpClient
{
public async Task<HttpResponseMessage> RunAsyncGet()
{
HttpClient client = new HttpClient();
return await client.GetAsync("https://www.google.no").ConfigureAwait(false);
}
}
partial class Form1
{
private IContainer components;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "Form1";
}
#endregion
}
}
- 异步的HttpClient代码第一次运行良好。
- 然后,我运行第二个异步代码并使用 ContinueWith 返回 UI 上下文,它运行良好。
- 我再次运行 HttClient 代码,但它死锁了,因为这一次 ConfigureAwait(false) 没有更改上下文。
【问题讨论】:
-
如果这是一个演示问题的实际完整示例,那就太好了。不幸的是,事实并非如此,所以我们只能猜测。如果可以,请尝试创建minimal reproducible example。
-
您好,很高兴知道您真正想要实现的目标。由于您为异步操作混合了不同的技术,并且代码有点难以理解。例如 RunAsyncPost 方法被称为 DoHttpWork。
标签: c# .net asynchronous async-await