异步关键字和的TaskScheduler的选择 [英] async keyword and choice of the TaskScheduler

查看:138
本文介绍了异步关键字和的TaskScheduler的选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道用async关键字编译时,编译器选择的TaskScheduler的方式背后的原因。

I would like to know the reasoning behind the way the compiler choose the TaskScheduler when compiling using the async keyword.

我的测试方法由SignalR(ASP.NET主机,IIS8,WebSocket的运输)的OnConnectedAsync方法。

My test method is called by SignalR (ASP.NET host, IIS8, websocket transport) on the OnConnectedAsync method.

protected override async Task OnConnectedAsync(IRequest request, string connectionId)
{
   SendUpdates();
}

启动对当前同步上下文任务将导致在System.Web.AspNetSynchronizationContext.OperationStarted()一​​个InvalidOperationException

Starting a task on the Current synchronization context will result to an InvalidOperationException in System.Web.AspNetSynchronizationContext.OperationStarted()

这是异步操作不能在这个时间开始。异步操作只能在异步处理程序或模块内或在在页面生命周期的某些事件开始。如果在执行一个页面出现了这种异常,保证页面标记<%@页面异步=真正的%方式>

An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>.

精细。有了这个SendUpdates定义,我得到了上面的异常:

Fine. With this SendUpdates definition, I get the above exception:

    private async void SendUpdates()
    {
        Task.Run(async () =>
            {
                while (true)
                {
                    await Task.Delay(1000);
                    await Connection.Broadcast("blabla");
                }
            });

    }

不过,更有趣的是,当我不明白的例外。以下工作:

But even more interesting is when I don't get the exception. The following works:

    private void SendUpdates()

和下面的作品太

    private async Task SendUpdates()

此最后一个工作过,但它的基本相同的上述实施例。

this last one works too, but it's essentially the same as the above example.

    private Task SendUpdates()
    {
        return Task.Run(async () =>
            {
                while (true)
                {
                    await Task.Delay(1000);
                    await Connection.Broadcast("blabla");
                }
            });

    }

你知道编译器如何选择在这里使用的调度?

Do you know how the compiler choose which scheduler to use here?

推荐答案

其中一个主要的指导方针以书面形式异步 code是避异步无效 - 即,使用异步任务而不是的异步无效除非你'重新实施一个异步事件处理程序。

One of the primary guidelines in writing async code is "avoid async void" - that is, use async Task instead of async void unless you're implementing an async event handler.

异步无效方法使用的 OperationStarted 的SynchronizationContext OperationCompleted ;看到我的MSDN文章这是所有关于SynchronizationContext的了解更多详情。

async void methods use SynchronizationContext's OperationStarted and OperationCompleted; see my MSDN article It's All about the SynchronizationContext for more details.

ASP.NET检测调用 OperationStarted 和(正确地)拒绝它,因为它是非法的把一个异步事件处理程序存在。当你纠正code使用异步任务,然后ASP.NET不再看到一个异步事件处理程序

ASP.NET detects the call to OperationStarted and (correctly) rejects it because it's illegal to put an async event handler there. When you correct the code to use async Task, then ASP.NET no longer sees an async event handler.

您可能会发现我的介绍到异步 / 等待帖子有帮助的。

You may find my intro to async / await post helpful.

这篇关于异步关键字和的TaskScheduler的选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆