如何将任务内静态属性的值“锁定”为任务启动时的值?

问题描述 投票:0回答:1

我想启动一个长时间运行的任务,它将使用静态类上的静态属性的值。我希望它在启动任务时“捕获”该值,并且继续使用该值,即使/当该静态属性在任务“外部”发生更改时。

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

c# multithreading asynchronous
1个回答
0
投票

这听起来像是

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 ''
© www.soinside.com 2019 - 2024. All rights reserved.