0

有没有一种将线程本地数据传递到 ActionBlock 的好方法,这样如果您在其 DataFlowExecutionOptions 中指定 MaxDegreeOfParallelization 为 > 1,那么执行该操作的每个任务都会有自己的线程本地数据?

这是我的一些代码,可能会阐明我想要做什么:

var options = new ExecutionDataflowBlockOptions() 
     {
        MaxDegreeOfParallelism = 12
     };

ActionBlock<int> actionBlock = new ActionBlock<int>(PerformAction, options);

List<int> resultsList = new List<int>();

void PerformAction(int i)
{
    // do some work

    // add them to resultsList 

    // i want to make sure that each thread that executes this method has its 
    // own copy of resultsList 
}

我希望能够让 ActionBlock 调用我提供的线程本地初始化函数。像这样的东西:

new ActionBlock<int>(PerformAction, options, () => new List<int>()); 

并让它将我的线程本地数据传递给我的 Action 函数:

void PerformAction(int i, List<int> localUserData) {...}
4

1 回答 1

2

我仍然不明白为什么您需要数据流块中的线程本地列表。你是对的,TDF 没有对线程局部值的任何明确支持(方式Parallel.ForEach()确实如此)。但这并不意味着您不能使用线程本地值,您只需要手动执行所有操作,使用ThreadLocal(我认为[ThreadStatic]在这里效果不佳,因为它不允许您跟踪所有线程本地实例)。例如:

private static ThreadLocal<List<int>> threadLocalList;

private static void Main()
{
    threadLocalList = new ThreadLocal<List<int>>(() => new List<int>(), true);

    var block = new ActionBlock<int>(
        (Action<int>)PerformAction,
        new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });

    for (int i = 0; i < 10; i++)
        block.Post(i);

    block.Complete();
    block.Completion.Wait();

    foreach (var list in threadLocalList.Values)
        Console.WriteLine(string.Join(", ", list));

    threadLocalList.Dispose();
}

private static void PerformAction(int i)
{
    threadLocalList.Value.Add(i * i);
}
于 2013-02-05T00:53:09.537 回答