我一直在网上看,我有一些问题,希望有人在这里可以回答我。 我正在尝试解决导致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)
        }
    }
}

实际上,我们在一个循环(从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

即使我在try catch块中强制发生异常(测试我们的错误记录器),它也会被我们的错误记录器正确捕获并记录。 看起来某些线程在请求​​完成后仍在尝试执行SynchronizationContext.Post。 我认为我们不正确地使用C#5的async / await,因为FireAndForgetAsync正在等待,但没有别的。 所以,我们说我们要等待,然后离开。 http请求结束,然后由于没有任何东西可以同步,它无法自动同步。 不好,因为这完全崩溃IIS。 我主要是在寻找其他人的输入,因为我不太熟悉C#5中的async / await以及适当的解决方案。 由于我们不想等待它完成,因此从FireAndForgetAsync方法中删除await和async修饰符似乎应该可以解决问题。

===============>>#1 票数:6

除非在Task.Run lambda完成后你有事情要做,否则你不应该做await 通过执行await ,您实际上要求在返回的Task完成之前恢复上下文以基本上执行no-op。

如果你一个理由做一个await (即应在之后做了一些工作Task.Run拉姆达完成),你不希望它试图恢复的背景下,那么你可以使用ConfigureAwait(false)的任务从Task.Run返回。

看到这篇文章的一个很好的解释:

===============>>#2 票数:6

这个服务呼叫应该是一个火灾和忘记呼叫类型。

希望你没有任何重要的代码,因为IIS不是这样设计的

[堆栈跟踪] ... LegacyAspNetSynchronizationContext ...

红色的标志! LegacyAspNetSynchronizationContext无法与asyncawait完美LegacyAspNetSynchronizationContext

请确保您在web.config中具有以下设置:

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

如果您在FireAndForgetAsync中执行实际的业务逻辑,那么您应该更改您的体系结构:将DoAction后工作到持久存储(例如,Azure队列)并具有独立的非IIS服务(例如,Azure工作者角色)处理在队列中工作。

如果您的FireAndForgetAsync工作不重要,那么您可以在我的博客上使用类似BackgroundTaskManager类型的东西来缓解这种方法的问题......

  ask by Acquire translate from so

未解决问题?本站智能推荐:

2回复

在同步调用方法中调用异步等待方法

这只是在窗口服务中即时通讯的想法。 我从这段视频中得到了实现并行处理的想法。 我有两个不同的方法和一个模型类。 型号分类代码: 方法是这样的: 我只想获取所有排队的电子邮件,然后并行发送,然后等待直到它已经发送。 我避免在收到的每封电子邮件上使用foreach 。
2回复

在没有等待#2的情况下调用异步方法

我有一个异步方法: 我这样称呼这个方法: 我可以从同步方法调用相同的方法,而不使用await关键字吗? 例如: 我认为这会导致僵局。 编辑 调用上面的方法会使调用永远不会结束。 (该方法不再到达终点)
1回复

调试异步/等待(调用堆栈)中的异常

我使用Async / Await释放我的UI-Thread并完成多线程。 我遇到异常时遇到问题。 我的Async部件的Call Stack总是从ThreadPoolWorkQue.Dipatch()开始,这对我没什么帮助。 我找到了MSDN文章Andrew Stasyuk。 Asyn
1回复

具有顶级功能的嵌套异步调用正在等待

我有这种情况,想在走那条路线之前先检查一下是否可行。 我有一个webApi项目,有一个委托处理程序,它在HttpContext.Current.Items中添加了一些数据。 在控制器中,我正在使用configureawait(false)进行异步调用。 在库DLL中相同。 总体代
3回复

了解.NET中的等待和异步

我正在研究使用Bootstrap协议来更新机器中多个节点的固件的重构代码。 当前代码看起来像这样(伪代码): 我想做的就是将其转换为async-await,但仍要求我不要立即回到调用方。 我该怎么做呢? 这可能吗? 由于await-async一直传播到顶部,这将是正确的做法吗?
5回复

导致死锁的异步/等待示例

我遇到了一些使用c#的async / await关键字进行异步编程的最佳实践(我是c#5.0的新手)。 给出的建议之一如下: 稳定性:了解您的同步上下文 ...某些同步上下文是不可重入的和单线程的。 这意味着在给定时间只能在上下文中执行一个工作单元。 Windows UI线
1回复

foreach内部未等待异步调用

关闭。 这个问题是题外话。 它当前不接受答案。 了解更多 。 想改善这个问题吗? 更新问
1回复

无法等待异步扩展方法

情况非常简单 - 我编写了一个扩展方法,并使其与返回类型Task<T>异步。 但是当我尝试使用await调用它时,编译器会抛出一个错误,表明扩展方法根本没有被识别为异步。 这是我的代码: 确切的错误信息是这样的: 'await'运算符只能在异步方法中使用。 考
1回复

如何从异步/等待的父级的所有嵌套任务中获取所有异常?

重新使用此答案中经过稍微修改的代码,如何修改它以实现@svick的建议 : 但是,如果将Task保存到变量中并调用task.Exception.Flatten(),则将返回两个异常 ? 当我试图访问containingTask.Exception.Flatten().I
2回复

当等待是最后一次时,不必要的异步/等待?

我最近一直在处理异步等待 (阅读包括Stephen和Jon最后两章在内的所有可能的文章),但我得出结论,我不知道它是否100%正确。 - 因此我的问题。 由于async只允许单词await出现,所以我会把async放在一边。 AFAIU等待着继续。 而不是编写功能(连续)代码,