Acq*_*ire 3 c# async-await c#-5.0
我一直在网上看,我有一些问题,希望有人在这里可以回答我.我正在尝试解决导致IIS崩溃的问题.该服务呼叫应该是一种火灾和忘记呼叫类型.如果失败,我们禁止并记录异常.因为它是一个长期运行的服务调用,所以它被实现为异步.当前实现有几个嵌套方法调用如下:
// in first service
public void PerformService(some params)
{
// setup and validation
DoAction();
}
private void DoAction()
{
// final setup
OtherService.FireAndForgetAsync(some params);
}
// in the other service (OtherService)
public async Task FireAndForgetAsync()
{
await Task.Run(() =>
{
try
{
// do some long running stuff
}
catch (Exception e)
{
ErrorLogger.LogError(e)
}
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,我们在一个循环(从0到多次迭代)中调用PerformService并且当前得到以下异常:
System.NullReferenceException: Object reference not set to an instance of an object. at
System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonati onContext) at
System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationCo ntext) at
System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state) at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallb ack callback, Object state) at System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback call back, Object state) at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAct ion(Object state) at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback c allback, Object
Run Code Online (Sandbox Code Playgroud)
即使我在try catch块中强制发生异常(测试我们的错误记录器),它也会被我们的错误记录器正确捕获并记录.看起来某些线程在请求完成后仍在尝试执行SynchronizationContext.Post.我认为我们不正确地使用C#5的async/await,因为FireAndForgetAsync正在等待,但没有别的.所以,我们说我们要等待,然后离开.http请求结束,然后由于没有任何东西可以同步,它无法自动同步.不好,因为这完全崩溃IIS.我主要是在寻找其他人的输入,因为我不太熟悉C#5中的async/await以及适当的解决方案.既然我们不想等到它完成,
你不应该这样做,await除非你在Task.Runlambda完成后有事可做.通过执行此操作await,您实际上要求在返回的Task完成之前将上下文恢复为基本上执行no-op.
如果你有一个理由做的await(后应该做即一些工作Task.Run拉姆达完成),你不希望它试图恢复的背景下,那么你可以使用ConfigureAwait(false)在任务从返回Task.Run.
看到这篇文章的一个很好的解释:
该服务呼叫应该是一种火灾和忘记呼叫类型.
希望你没有任何重要的代码,因为IIS不是这样设计的.
[堆栈跟踪] ... LegacyAspNetSynchronizationContext ...
红色标志!LegacyAspNetSynchronizationContext不完美播放async和await.
请确保您在web.config中具有以下设置:
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
Run Code Online (Sandbox Code Playgroud)
如果您正在进行实际的业务逻辑FireAndForgetAsync,那么您应该更改您的体系结构:将DoAction后期工作发布到持久存储(例如,Azure队列)并拥有独立的非IIS服务(例如,Azure工作者角色)处理工作队列.
如果你的FireAndForgetAsync工作不重要,那么你可以使用BackgroundTaskManager我博客上的类型来减轻这种方法的问题......