【发布时间】:2020-03-28 07:21:42
【问题描述】:
在一个 ASP.NET 应用程序中,我有一个动作,当它被点击时,以下列方式启动一个新的后台任务:
Task.Factory.StartNew(async () => await somethingWithCpuAndIo(input), CancellationToken.None, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext());
我不是在等待它,我只是希望它启动,并继续在后台执行它的工作。 之后,我立即向客户端返回响应。
尽管出于某种原因,在执行后台工作的初始线程遇到等待方法完成的 await 之后,调试时,我成功解析了该方法,但在返回时,执行只是停止并且不会在该点以下继续.
有趣的是,如果我完全等待这个任务(使用双精度 await),一切都会按预期进行。
这是由于 SynchronizationContext 造成的吗?在我返回响应的那一刻,同步上下文被释放/删除? (方法内部使用了 SynchronizationContext)
如果是因为这个,问题到底发生在哪里?
A) 当调度器尝试在给定的同步上下文上分配工作时,它已经被释放,所以不会提供任何东西
B) 在方法执行的某个地方,当我向客户端返回响应时,同步上下文会丢失,不管其他任何事情。
C) 完全不同的东西?
如果是 A),我应该能够通过在安排工作和返回响应之间简单地执行 Thread.Sleep() 来解决此问题。 (试过了,还是不行。)
如果是 B) 我不知道如何解决这个问题。我们将不胜感激。
【问题讨论】:
-
Task.Factory.StartNew(async () =>返回一个Task<Task>。外部任务只是创建内部任务。创建任务通常不是长时间运行的工作。 -
这是一个有趣的阅读:How to run Background Tasks in ASP.NET。这是另一个:Fire and Forget on ASP.NET.
-
@TheodorZoulias 的意思是我们在使用异步 lambda 时永远不应该传递
Task.LongRunning? -
“从不”是一个强词。通常你应该有no reason 来使用
TaskCreationOptions.LongRunning选项和asynclambdas,但可能会有一些罕见的例外。通常,此选项旨在用作优化技术,即"don't use it unless you find that you really need it"。 ????
标签: c# asp.net multithreading asynchronous async-await