在C#中,当覆盖方法时,允许在原始方法不是时使覆盖异步.这似乎很糟糕.
令我惊讶的问题是:我被引入以协助负载测试问题.在大约500个并发用户中,登录过程将分解为重定向循环.IIS正在使用消息"在异步操作仍处于挂起状态时完成异步模块或处理程序"来记录异常.一些搜索让我觉得有人在滥用async void
,但我对源头的快速搜索一无所获.
可悲的是,我正在寻找async\s*void
(正则表达式搜索)我应该寻找更多的东西async\s*[^T]
(假设任务不完全合格......你明白了).
我后来发现的是async override void onActionExecuting
在一个基本控制器中.显然,这必须是问题,而且确实如此.修复它(使其暂时同步)解决了问题.
但它给我留下了一个问题:为什么当调用代码永远不会等待它时,你可以将覆盖标记为异步?
sha*_*y__ 27
当基类(或接口)声明一个返回Task的虚方法时,只要返回Task,就可以覆盖它.该async
关键字仅仅是一个暗示,编译器将您的方法进入状态机.虽然编译器在你的方法上做了它的黑魔法,但编译的方法仍然返回一个Task.
至于void
虚拟方法,可以覆盖一个没有的async
关键字(明显),并在其内启动非等待任务.这是一种当你重写它会发生什么用的async
关键字,并使用await
在体内.调用者不会等待创建的任务(因为"原始"签名是void
).两种情况都相似*:
public override void MyVirtualMethod()
{
// Will create a non awaited Task (explicitly)
Task.Factory.StartNew(()=> SomeTaskMethod());
}
public override async void MyVirtualMethod()
{
// Will create a non awaited Task (the caller cannot await void)
await SomeTaskMethod();
}
Run Code Online (Sandbox Code Playgroud)
Stephen Cleary的文章对此有一些注意事项:
*SomeTaskMethod
底层框架,SynchronizationContext和其他因素的实现可能会并将导致上述每种方法的不同结果.
Kir*_*ill 11
您可以覆盖async
方法,因为async不是方法签名的一部分.实际上,异步允许await
在方法中使用关键字,方法是在里面创建一个状态机.
你可以在这里找到更多关于async的信息:http://blog.sublogic.com/2012/05/14/async-isnt-really-part-of-your-method-signature/
async
不属于"合同"的一部分.这是一个实现细节,在我看来,不幸的是,它出现在错误的地方.
它是完全合法的改变(非async
)方法返回Task
到async
没有,作为一个重大更改一个(或反之亦然),并且不要求呼叫者重新编译.
进一步表明它不是合同的一部分是你不允许async
在接口内标记功能,因为这里完全可以async
用非覆盖,async
反之亦然.
归档时间: |
|
查看次数: |
10816 次 |
最近记录: |