C# 在任务中使用ThreadStatic字段
开始编辑 “正确”的方法是使用SynchronizationContext,如下所述: 我相信在4.5 SynchronizationContext中,使用async/await关键字会自动为您处理,但还并没有做足够的工作来确认 在4.0中,您可能希望利用“TaskScheduler.FromCurrentSynchronizationContext”捕获当前线程的上下文(在我的例子中,这将包括HttpContext,但BCL的各个部分提供类似的构造) 结束编辑 主要问题是: 以下是与任务共享“上下文”的“安全”机制吗? 在我的用例中,如果不深入太多细节,就不可能直接将上下文下推到操作中C# 在任务中使用ThreadStatic字段,c#,thread-safety,task-parallel-library,C#,Thread Safety,Task Parallel Library,开始编辑 “正确”的方法是使用SynchronizationContext,如下所述: 我相信在4.5 SynchronizationContext中,使用async/await关键字会自动为您处理,但还并没有做足够的工作来确认 在4.0中,您可能希望利用“TaskScheduler.FromCurrentSynchronizationContext”捕获当前线程的上下文(在我的例子中,这将包括HttpContext,但BCL的各个部分提供类似的构造) 结束编辑 主要问题是: 以下是与任务共享“
public static class ContextCaller{
[ThreadStatic]
public static object SharedState;
public static Task InvokeWithContext(this Action theAction){
//We're still running in the "outer" context,
//so we can collect a variable and store it in the thread-static
//field by closing it into the task.
var context = new object();
var t = new Task(()=>{
try{
//close in the context
SharedState = context;
theAction();
}
finally{
//teardown the shared state.
SharedState = null;
}
});
t.Start();
return t;
}
}
现在是客户端代码:
//client code:
Action doWork = ()=>{
var state = ContextCaller.SharedState;
//do work on state, potentially throwing an exception in the process.
};
//cause the task to be invoked with some data available only on this thread.
doWork.InvokeWithContext();
根据我对任务和线程之间关系的理解,以上内容应该是安全的,因为:
除了显式地将参数关闭到“theAction”之外,还有其他更好的模式用于定义任务的上下文吗?我看不出代码不能正常工作的任何技术原因
但我也认为这样做是一种不好的做法,只有在没有其他方法的情况下,我才会使用这样的方法。我认为在方法中添加另一个重载来执行
操作
(或者更好,使用强类型参数)不应该是一个重大的改变。我意识到这有点“聪明”,我意识到使用异步/等待支持隐式地在所有地方创建任务,我关于不生成任务的假设将越来越难以实施。我假设不可能将操作更改为操作,而只将上下文作为参数传递?正确,调用方没有直接访问“上下文”变量的权限,添加它们会给我带来其他问题。我知道我可以通过操作传递状态,问题是“doWork()”对HttpContext有一个间接依赖,它可以/将在任务运行之前消失。如果你在ASP.NET中,为什么要使用任务
s?能否在ASP.NET同步上下文上运行任务
?我相信这样做可以解决HttpContext依赖性。我将此标记为可接受的答案,因为它确实涵盖了提出的问题,但我认为SynchronizationContext是一条路,并将在上面的问题中概述这一点。