2013-03-07 1 views
1

Что я пытаюсь выполнить, так это у меня есть блок действий с MaxDegreeOfParallelism = 4. Я хочу создать один локальный экземпляр объекта сеанса, который у меня есть для каждого параллельного пути. Поэтому я хочу суммировать 4 объекта сеанса. Если бы это было тема, я хотел бы создать что-то вроде:TPL локальное хранилище данных или что-то в этом роде

ThreadLocal<Session> sessionPerThread = new ThreadLocal<Session>(() => new Session()); 

Я знаю, что блоки не являются нитями, так я ищу что-то подобное, но для блоков. Любой способ создать это?

Этот блок находится в обслуживании и работает в течение нескольких месяцев подряд. В течение этого периода времени для каждого параллельного слота блока используется множество потоков, поэтому локальное хранилище потоков не подходит. Мне нужно что-то связанное с слотом логического блока. Также этот блок никогда не завершается, он запускает всю жизнь службы.

Примечание: приведенный выше ответ недействителен для того, что я прошу. Я специально прошу что-то другое, чем thread local, и выше ответ использует thread local. Это совсем другой вопрос.

+0

Возможный дубликат [TPL Data Flow Thread Local Data] (http://stackoverflow.com/questions/14693452/tpl-data-flow-thread-local-data) – svick

+0

Нет, это не дубликат потока данных TPL Локальные данные по потоку. Они спрашивают, как использовать «Локальные данные потока», это явно то, что я не хочу использовать. Я хочу что-то, что привязано к параллельным слотам блока, а не к нитям. Любой данный слот в блоке может пересекать много потоков за время жизни блока, это не то, что я хочу. –

+0

За исключением того, что блоки потока данных не имеют понятия «слоты». Существует максимальная степень параллелизма, но это не одно и то же, нет слота, который будет перемещаться между потоками. Не могли бы вы объяснить, почему именно вы хотите это сделать? – svick

ответ

4

Как вы уже знаете, блоки потока данных абсолютно не гарантируют корреляцию между блоками, исполнением и потоками. Даже при максимальном параллелизме, установленном в 4, все 4 задачи могут выполняться в одном и том же потоке. Или отдельная задача может выполняться во многих потоках.

Учитывая, что вы в конечном итоге хотите использовать п экземпляров дорогого сервиса для п степени параллелизма, давайте рассмотрим поток данных полностью из картины на минуту, так как это не помогает (или непосредственно препятствовать) от любого общего решения этой проблемы. На самом деле это довольно просто. Вы можете использовать ConcurrentStack<T>, где T - тип вашего сервиса, который стоит создавать. У вас есть код, который появляется в верхней части метода (или делегат), который представляет одну из ваших параллельных единиц работы:

private ConcurrentStack<T> reusableServices; 

private void DoWork() { 
    T service; 
    if (!this.reusableServices.TryPop(out service)) { 
     service = new T(); // expensive construction 
    } 

    // Use your shared service. 
    //// Code here. 

    // Put the service back when we're done with it so someone else can use it. 
    this.reusableServices.Push(service); 
} 

Теперь, таким образом, вы можете быстро увидеть, что вы создаете именно столько экземпляров вашего поскольку у вас есть параллельные исполнения DoWork(). Вам даже не нужно жестко кодировать степень параллелизма, которую вы ожидаете. И он ортогонален как вы фактически планируете этот параллелизм (поэтому threadpool, Dataflow, PLINQ и т. Д. Не имеет значения).

Таким образом, вы можете использовать DoWork() в качестве делегата блока потока данных, и вы готовы к работе.

Конечно, нет ничего волшебного в ConcurrentStack<T> здесь, за исключением того, что блокировки вокруг push и pop встроены в тип, поэтому вам не нужно это делать самостоятельно.

+0

Да, я знаком с этим шаблоном, но я искал способ сделать это непосредственно с помощью блоков. Я создал пулы объектов аналогичным образом, но используя ConcurrentBag . Я собираюсь дать ему еще немного времени, чтобы узнать, знает ли кто-нибудь о способе делать это непосредственно с блоками, если нет, я помету ваш в качестве ответа. –

+0

Как можно выполнить 4 синхронных 'Task' в одном потоке (при условии, что они фактически выполняются параллельно, а не только последовательно). Или вы имели в виду асинхронный 'Task'? – svick

+0

@svick Dataflow не может гарантировать параллельное выполнение. Все, что он может сделать, это расписание * n * задач для назначенного TaskScheduler сразу. В этот момент задача TaskScheduler определяет, когда фактически выполняются задачи. Предположим, что TaskScheduler на самом деле тот, который выполняет все в потоке STA приложения для окон. Ну, в таком случае все «параллельные» задачи получаются сразу, но выполняются только по одному, в том же потоке STA. Если TaskScheduler был файловым файлом по умолчанию, threadpool все равно может выполнить все из них в одном потоке - обычно, но это может произойти. –

Смежные вопросы