Фабрика задач и локальное хранилище потоков

Я создаю x количество задач из фабрики задач в цикле. Эти задачи выполняются и выполняют некоторую работу, пока я жду завершения всех задач.

Вопрос, который у меня есть, заключается в том, что каждая задача/поток инициализирует свою собственную копию дорогостоящего объекта, скажем, DocumentObject. В идеале я хотел бы повторно использовать этот объект для каждой задачи/потока, чтобы при повторном использовании его как части фабрики не было необходимости повторно создавать.

Возможно ли что-то подобное с theThreadLocalconcept в .Net.


person Science_Fiction    schedule 24.01.2014    source источник
comment
Не могли бы вы просто создать экземпляр одного DocumentObject перед запуском параллельного цикла?   -  person xspydr    schedule 24.01.2014
comment
Но объект небезопасен для потоков.   -  person Science_Fiction    schedule 24.01.2014


Ответы (2)


Не следует использовать ThreadLocal с параллельным Задачи, очень сложно убирать за собой, если у вас есть ресурсы, которые нужно утилизировать, если вы не отслеживаете объекты, которые создаете, по мере их создания. Это связано с тем, что задачи создаются в пуле потоков, поэтому невозможно гарантировать, что вы снова вернетесь к тому же потоку, чтобы выполнить свою работу по очистке1.

Лучший способ справиться с этим — использовать либо Parallel.For< /a> или Parallel.ForEach, который занимает в лямбдаде, которая создает объект, привязанный к задаче и используемый одновременно только одним потоком (с именами localInit и localFinally).

Parallel.ForEach(GetSomeData(), () => new DocumentObject(),
    (sourceData, loopState, localData)
    {
        //localData is the DocumentObject that unique per thread.

        //...

        return localData; //Passes the class to the next task that is going to use it.
    }
    (localData) => 
    {
        localData.Dispose(); //Do any work here you need to do when a thread is done with the object.
    }

Конечно, если вам нечего делать в localFinally, используйте ThreadLocal, если хотите.


1. В версии 4.5 добавлено Values, чтобы иметь возможность снова получить доступ к объектам без необходимости отслеживать их при создании.

person Scott Chamberlain    schedule 24.01.2014

Некоторые идеи:

  1. Создайте копию вашего ExpensiveObject в основном процессе, а затем ваши задачи получат доступ к основной копии (по значению или ссылке, по желанию)
  2. Используйте статический класс для вашего ExpensiveObject
person John Jeheimer    schedule 24.01.2014
comment
Да.. Я почему-то сомневаюсь, что «дорогой объект» будет иметь достаточную потокобезопасность, чтобы использовать один статический объект. - person Martin James; 24.01.2014