“UseTaskFriendlySynchronizationContext”是什么意思?

68

在 ASP.NET 4.5 中有一个新的应用程序设置。

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

这样的代码可以在asp.net 4.0中运行

protected void Button1_Click(object sender, EventArgs e)
{
    CallAysnc();
}

public void CallAysnc()
{
    AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(Guid.NewGuid().ToString());

    WebClient client = new WebClient();
    client.DownloadStringCompleted += (object sender, DownloadStringCompletedEventArgs e) =>
    {
        asyncOp.PostOperationCompleted(CallCompleted, e.Result);
    };
    client.DownloadStringAsync(new Uri("http://www.google.com"));
}

private void CallCompleted(object args)
{
    Response.Write(args.ToString());
}

但是在asp.net 4.5中不起作用,当我移除新的appsetting后,它又起作用了!

那么"UseTaskFriendlySynchronizationContext"是什么意思?

2个回答

77

关于UseTaskFriendlySynchronizationContext,来自Microsoft论坛的解释:

这告诉ASP.NET使用全新的异步管道,遵循CLR启动异步操作的约定,包括在需要时将线程返回到线程池。 ASP.NET 4.0及以下版本遵循自己的约定,与CLR指南相违背,如果未启用此项切换,则异步方法非常容易以同步方式运行,死锁请求,或者行为不符合预期。

此外,我认为AsyncOperationManager是为桌面应用程序设计的。 对于ASP.NET应用程序,您应该使用RegisterAsyncTask并设置<%@ Page Async =“true”请参阅此处以获取更多详细信息

因此,使用新的C#关键字,您的示例将如下所示:

protected void Button1_Click(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(CallAysnc));
}

private async Task CallAysnc()
{
    var res = await new WebClient().DownloadStringTaskAsync("http://www.google.com");
    Response.Write(res);
}

目标是在正式版中支持以下功能,但目前在测试版中不支持:

protected async void Button1_Click(object sender, EventArgs e)
{
    var res = await new WebClient().DownloadStringTaskAsync("http://www.google.com");
    Response.Write(res);
}

我使用了目标代码,它运行良好。如何知道它当前不受支持?什么情况下不支持? - Dozer
1
@Dozer,我猜你没有将UseTaskFriendlySynchronizationContext设置为true?我会收到一个关于Response不可用的错误(容易解决,但如果编码访问它的控件无法更改,则不行)。如果你点击那个链接进入Microsoft论坛,你可以看到我遇到的一些问题以及一位Microsoft员工关于它不受支持的评论。我有印象它还没有自动插入到RegisterAsyncTask中,原因是有一些问题(不知道是什么,但你可以在那个论坛上问),如果没有的话,你将无法获得比同步运行更多的好处。 - Michael
MSDN上的答案说:“在您的特定示例中,如果没有设置<appSettings>开关,则具有异步void方法实际上会在页面中引入竞争条件,其中DataBind()方法不能保证在页面实际呈现并将其输出发送到客户端之前被调用。”但是我尝试了一下,页面总是在DataBind()方法之后呈现。 - Dozer
在移除了<appSettings>后,我发现了一个问题。如果你编写了两个方法:async Page_Load和async Button1_Click。当你点击按钮时,这两个方法将并行运行。我认为这种情况是一种“竞态条件”。 - Dozer

13

以下是引用自ASP.NET 4.5.1appSettings文档中的详细信息:

aspnet:UseTaskFriendlySynchronizationContext

指定ASP.NET 4.5中异步代码路径的行为。

...

如果将此键值设置为false [默认值],则ASP.NET 4.5中的异步代码路径的行为与ASP.NET 4.0相同。如果将此键值设置为true,则ASP.NET 4.5将使用针对返回任务(Task-returning)API进行优化的代码路径。对于启用WebSockets的应用程序、在Web Forms页面中使用基于任务(Task-based)的异步和某些其他异步行为,设置此兼容性开关是强制性的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接