以干净的 AsyncLocal 状态启动任务
Start a task with clean AsyncLocal state
在 ASP.NET Core 中,我使用 IHttpContextAccessor
访问当前的 HttpContext
。 HttpContextAccessor
uses AsyncLocal<T>
.
在一种情况下,我试图从请求中启动 Task
,在请求结束后应该继续 运行(长 运行,后台任务),我正在尝试将其从当前执行上下文中分离出来,以便 IHttpContextAccessor
returns null
(否则我正在访问无效的 HttpContext
)。
我尝试了 Task.Run
、Thread.Start
,但每次,上下文似乎都会延续,并且 IHttpContextAccessor
returns 无论我尝试什么,旧的上下文(有时甚至是上下文来自其他请求)。
我怎样才能启动一个具有干净 AsyncLocal
状态的任务,以便 IHttpContextAccessor
returns null
?
您可以等待漫长的 运行ning 任务并在 await 中将 HttpContext
设置为 null 。对于任务之外的所有代码都是安全的。
[Fact]
public async Task AsyncLocalTest()
{
_accessor = new HttpContextAccessor();
_accessor.HttpContext = new DefaultHttpContext();
await LongRunningTaskAsync();
Assert.True(_accessor.HttpContext != null);
}
private async Task LongRunningTaskAsync()
{
_accessor.HttpContext = null;
}
你可以运行一个单独的线程,没关系。
Task.Run(async () => await LongRunningTaskAsync());
只需让任务等待清理 HttpContext
仅针对任务的异步上下文。
迟到的答案,但可能对其他人有用。您可以通过在提交任务时抑制 ExecutionContext 流来做到这一点:
ExecutionContext.SuppressFlow();
var task = Task.Run(async () => {
await LongRunningMethodAsync();
});
ExecutionContext.RestoreFlow();
或更好:
using (ExecutionContext.SuppressFlow()) {
var task = Task.Run(async () => {
await LongRunningMethodAsync();
});
}
这将防止在提交的任务中捕获 ExecutionContext。因此它将具有 'clean' AsyncLocal 状态。
如上所述,如果它是 CPU 密集的后台工作,我不会在 ASP.net 中执行此操作。
在 ASP.NET Core 中,我使用 IHttpContextAccessor
访问当前的 HttpContext
。 HttpContextAccessor
uses AsyncLocal<T>
.
在一种情况下,我试图从请求中启动 Task
,在请求结束后应该继续 运行(长 运行,后台任务),我正在尝试将其从当前执行上下文中分离出来,以便 IHttpContextAccessor
returns null
(否则我正在访问无效的 HttpContext
)。
我尝试了 Task.Run
、Thread.Start
,但每次,上下文似乎都会延续,并且 IHttpContextAccessor
returns 无论我尝试什么,旧的上下文(有时甚至是上下文来自其他请求)。
我怎样才能启动一个具有干净 AsyncLocal
状态的任务,以便 IHttpContextAccessor
returns null
?
您可以等待漫长的 运行ning 任务并在 await 中将 HttpContext
设置为 null 。对于任务之外的所有代码都是安全的。
[Fact]
public async Task AsyncLocalTest()
{
_accessor = new HttpContextAccessor();
_accessor.HttpContext = new DefaultHttpContext();
await LongRunningTaskAsync();
Assert.True(_accessor.HttpContext != null);
}
private async Task LongRunningTaskAsync()
{
_accessor.HttpContext = null;
}
你可以运行一个单独的线程,没关系。
Task.Run(async () => await LongRunningTaskAsync());
只需让任务等待清理 HttpContext
仅针对任务的异步上下文。
迟到的答案,但可能对其他人有用。您可以通过在提交任务时抑制 ExecutionContext 流来做到这一点:
ExecutionContext.SuppressFlow();
var task = Task.Run(async () => {
await LongRunningMethodAsync();
});
ExecutionContext.RestoreFlow();
或更好:
using (ExecutionContext.SuppressFlow()) {
var task = Task.Run(async () => {
await LongRunningMethodAsync();
});
}
这将防止在提交的任务中捕获 ExecutionContext。因此它将具有 'clean' AsyncLocal 状态。
如上所述,如果它是 CPU 密集的后台工作,我不会在 ASP.net 中执行此操作。