Поток данных TPL Локальные данные

Есть ли хороший способ передать локальные данные потока в ActionBlock, например, если вы укажете MaxDegreeOfParallelization в его DataFlowExecutionOptions равным> 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) {...}

1 ответ

Решение

Я до сих пор не понимаю, зачем вам локальный список потоков в блоке потока данных. И вы правы, что 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);
}
Другие вопросы по тегам