我想启动一个长时间运行的任务,它将使用静态类上的静态属性的值。我希望它在启动任务时“捕获”该值,并且继续使用该值,即使/当该静态属性在任务“外部”发生更改时。
MyStaticClass.MyStaticProperty = "foo";
Task.Run(() =>
{
// Assume this runs for 10 minutes...
// MyStaticClass.MyStaticProperty should continue to be "foo"
// because that's what it was when the task started
});
MyStaticClass.MyStaticProperty = "bar";
// Even though this executes milliseconds after the task starts,
// the value of this property inside the task should remain "foo"
实际上,我希望我的任务“复制”该值的状态并保留它自己的版本,与任务运行时“外部”发生的情况隔离。
更新:我不能只制作该值的本地副本,因为任务中的代码可能会调用其他代码,而其他代码又调用其他代码,等等。并且被调用的代码将不知道该值的本地副本变量。删除 X 级别的代码只会无知地调用
MyStaticClass.MyStaticProperty
这听起来像是
AsyncLocal<T>
的解决方案。文档中的 示例很好地解释了这一点。
using System;
using System.Threading;
using System.Threading.Tasks;
class Example
{
static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
static ThreadLocal<string> _threadLocalString = new ThreadLocal<string>();
static async Task AsyncMethodA()
{
// Start multiple async method calls, with different AsyncLocal values.
// We also set ThreadLocal values, to demonstrate how the two mechanisms differ.
_asyncLocalString.Value = "Value 1";
_threadLocalString.Value = "Value 1";
var t1 = AsyncMethodB("Value 1");
_asyncLocalString.Value = "Value 2";
_threadLocalString.Value = "Value 2";
var t2 = AsyncMethodB("Value 2");
// Await both calls
await t1;
await t2;
}
static async Task AsyncMethodB(string expectedValue)
{
Console.WriteLine("Entering AsyncMethodB.");
Console.WriteLine(" Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'",
expectedValue, _asyncLocalString.Value, _threadLocalString.Value);
await Task.Delay(100);
Console.WriteLine("Exiting AsyncMethodB.");
Console.WriteLine(" Expected '{0}', got '{1}', ThreadLocal value is '{2}'",
expectedValue, _asyncLocalString.Value, _threadLocalString.Value);
}
static async Task Main(string[] args)
{
await AsyncMethodA();
}
}
// The example displays the following output:
// Entering AsyncMethodB.
// Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1'
// Entering AsyncMethodB.
// Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2'
// Exiting AsyncMethodB.
// Expected 'Value 2', got 'Value 2', ThreadLocal value is ''
// Exiting AsyncMethodB.
// Expected 'Value 1', got 'Value 1', ThreadLocal value is ''