Обеспечение потокобезопасности

Я посреди записи приложения Windows Form C#, которое обрабатывает кавычки от рынка до алгоритма (стратегия) создать заказы к брокерской фирме. Это все, кажется, тестирует довольно хорошо, пока я не пытался создать в возможности выполнить несколько стратегий одновременно с каждой стратегией относительно своего собственного потока. В этой точке все начинает работать неправильно. Я полагаю, что у меня есть некоторые классы, которые не ориентированы на многопотоковое исполнение, которые управляют ошибочным поведением. Любое понимание о том, как я могу распараллелить это ориентированным на многопотоковое исполнение способом, глубоко ценится!

Путем Кавычки питаются в Алгоритмы, следующие: 1) События Данных Рынка запущены от программного обеспечения Брокеров до клиентского класса в моем программном обеспечении под названием ConnectionStatus. Когда событие Data рынка инициировано, объект Кавычки создается из текущих значений этих статических переменных, которые представляют Предложение, спрашивают и т.д. После того как кавычка создается, я пытаюсь отправлять ее в каждый из Алгоритмов Стратегии, которые работают. Вот код, который я использую, чтобы сделать это:

 foreach (StrategyAssembler assembler in StrategyAssembleList.GetStrategies())
 {                  
     BackgroundWorker thread = strategyThreadPool.GetFreeThread();
     if (thread != null)
     {
        thread.DoWork += new DoWorkEventHandler(assembler.NewIncomingQuote);
        thread.RunWorkerAsync(quote);
     }   
 }

StrategyAssembler является классом, который создает экземпляр Класса StrategyManager, который в свою очередь создает экземпляр стратегии, которая содержит фактические алгоритмы. Может быть 4 или 6 различных экземпляров StrategyAssembler, каждый из которых был добавлен к экземпляру Singleton StrategyAssembleList, который является BindingList.

Входящий объект кавычки передается в метод NewIncomingQuote Класса StrategyAssembler. Тот код следующие:

public void NewIncomingQuote(object sender, DoWorkEventArgs e)
    {
        Quote QUOTE = e.Argument as Quote;            

        lock (QuoteLocker)
        {
            manager.LiveQuote(QUOTE);

            priorQuote = QUOTE;
        }
    }

Я думал это при помощи блокировки прежде, чем передать кавычку в менеджера. LiveQuote (Кавычка кавычки) метод, что все объекты, которые используют кавычку "в нисходящем направлении" этой точки, смогли бы использовать кавычку ориентированным на многопотоковое исполнение способом, но тестирование показывает иначе. Существует ли способ, которым я мог поместить каждый экземпляр StrategyAssembler на его собственном потоке, который гарантирует, что все объекты, созданные Ассемблером Стратегии, ориентированы на многопотоковое исполнение и затем подают кавычку в StrategyAssembler? Действительно ли этот путь взглядов является соответствующим способом справиться с этой ситуацией?

Заранее спасибо за любую обратную связь или справку,

Learning1

6
задан spender 1 March 2010 в 19:40
поделиться

3 ответа

В вашем коде происходят две вещи:
1. Вы получили цитату из одного потока (производитель также известен как поток рыночных данных).
2. Вы отправляете цитату в другой поток (потребитель AKA StrategyAssembler).

На данный момент существует разногласия по поводу цитаты, другими словами, поток-производитель и каждый поток-потребитель (то есть каждый экземпляр стратегии) ​​могут изменять цитату, которую вы ему просто предоставляете. Чтобы снять конфликт, вы должны выполнить одно из трех действий:

  1. Синхронизировать все потоки с доступом к цитате.
    ИЛИ
  2. Сделайте цитату неизменной (и убедитесь, что производитель не заменяет ее).
    ИЛИ
  3. Раздайте каждому потребителю копию цитаты.

В вашем случае я бы посоветовал вам выбрать третий вариант, потому что блокировка дороже, чем копирование котировки (я надеюсь, что ваши котировки не очень большие) ... второй вариант тоже хорош, но ваша стратегия не должна изменять котировку .

Предоставляя каждому потребителю копию цитаты, вы гарантируете, что они не будут передавать какие-либо данные, поэтому никакой другой поток не изменит цитату, и вы устраните разногласия. Если ваши стратегии не создают никаких других потоков, то все готово.

В целом вам следует избегать блокировок и стараться минимизировать совместное использование данных, но если вы ДОЛЖНЫ обмениваться данными между потоками, вы должны делать это правильно:
Для того, чтобы для правильной синхронизации ваших стратегий они должны синхронизироваться с одним и тем же объектом QuoteLocker , т.е. QuoteLocker должен быть виден каждому потоку. Даже если вы сделаете это правильно и синхронизируете свои стратегии (заблокируйте QuoteLocker ), у вас также может не быть потоков ... вы будете выполнять накладные расходы на переключение контекста + блокировку, и ваши стратегии будут выполняться последовательно для одной и той же котировки.

Обновление по комментариям: Если вы оставите код как есть (это означает, что вы предоставляете копию цитаты для каждого потока), то я не понимаю, почему другие ваши стратегии не получат цитата до завершения первой стратегии ... ваша первая стратегия, скорее всего, начнет работать, пока создаются потоки для других стратегий. Весь смысл запуска ваших стратегий в отдельном потоке состоит в том, чтобы избежать именно этой проблемы ... вы запускаете новый поток, чтобы ваши другие стратегии не ожидали завершения друг друга.

Эта часть кода, скорее всего, завершится еще до того, как все ваши потоки начнут работать ...

foreach (StrategyAssembler assembler in StrategyAssembleList.GetStrategies())
 {                  
     BackgroundWorker thread = strategyThreadPool.GetFreeThread();
     if (thread != null)
     {
        thread.DoWork += new DoWorkEventHandler(assembler.NewIncomingQuote);
        Quote copy = CopyTheQuote(quote);// make an exact copy of the quote
        thread.RunWorkerAsync(copy);
     }   
 }

Ваш рыночный поток меняет фактическую котировку, пока вы создаете потоки? Рыночные каналы обычно предоставляют снимки, поэтому, если что-то не меняет вашу котировку, пока вы создаете потоки, то дизайн выше должен быть в порядке. Если есть проблема с дизайном, я могу предложить вам дизайн производителя и нескольких потребителей, основанный на очереди блокировки, которая также очень эффективна ( вы можете проверить это обсуждение, чтобы узнать, как это работает и я могу рассказать вам, как изменить его для вашего конкретного примера).

0
ответ дан 17 December 2019 в 22:12
поделиться

Блокировка должна происходить как при чтении, так и при записи в любое совместно используемое состояние. Без блокировок чтения код все еще может читать и писать одновременно.

Вы можете обернуть блокировку чтения и записи в диспетчер.

1
ответ дан 17 December 2019 в 22:12
поделиться

Если:

1) Стратегии вызываются через метод LiveQuote и могут изменять экземпляры Quote.

2) Изменения экземпляров Quote не должны быть общими для стратегий.

Перед вызовом LiveQuote() необходимо создать копию предоставленной Quote и передать в метод стратегии копию, а не исходную котировку. В зависимости от других требований, блокировка может вообще не понадобиться.

0
ответ дан 17 December 2019 в 22:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: