C # несколько источников, разные потоки, один обработчик событий - PullRequest
3 голосов
/ 10 августа 2010

Мне нужен кто-то с высокими навыками работы с потоками и создания событий.

У меня есть абстрактный класс A и два конкретных класса C1, C2 (например, плагины).

Поскольку мне нужно, чтобы они общались друг с другом, как, например, «плагин-приложение», «плагин-плагин», у меня есть метод ExecuteCommand в абстрактном классе, который должен выполнить это.Эта функция вызывает event для приложения, чтобы обработать определенную команду и вернуть результат (например, если одному плагину требуются данные из приложения, он вызывает ExecuteCommand из базы и ждет результата, который поступает с обработчиком событийобрабатывается по заявке).

protected object ExecuteCommand(SvcCmdType cmdType, params object[] inputParams)
{
  // this code has been simplified
  SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType, inputParams);

  // generate processing command event (it requires to fill in the result)
  OnProcessingAppCommand(this, eventArgs);

  return eventArgs.OutputParamsList; 
}

Проблема :

Если каждый из C1 и C2 имеют разныепотоки позади и одновременный вызов ExecuteCommand из своих собственных потоков, тогда точно мой дизайн будет нарушен, а возвращаемый результат будет неожиданным.

Каков лучший дизайн для этого сценария?Я думал использовать внутри ExecuteCommand асинхронные вызовы, например AsyncOperation ... но правильно ли это?

отредактировано: Наверное, я ищу: синхронноили асинхронный способ лучше для моего сценария?Или мне нужно обработать обработчик событий приложения внутри потока плагина или синхронизировать его где-нибудь в моем основном потоке?

Буду очень признателен за хорошее объяснение ваших рекомендаций

Спасибо.

1 Ответ

1 голос
/ 10 августа 2010

Обычный простой метод выполнения потоковой синхронизации на общем ресурсе или кодовом блоке заключается в использовании мьютекса (или, в данном случае, критической секции). Используйте оператор блокировки:

http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx

В этой статье говорится о блокировке указателя "this", но это может быть опасно, поскольку внешние вызывающие стороны также могут получить такую ​​же блокировку, которая может сломать вашу программу. Сделайте вашу блокировку на частной переменной класса.

Вот некоторая модификация вашего примера кода для включения блокировки / критической секции:

class SomeClass : ISomeInterface
{
  protected object ExecuteCommand(SvcCmdType cmdType, params object[] inputParams)
  {
    lock(executeCommandLock)
    {
      SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType, inputParams);
      OnProcessingAppCommand(this, eventArgs);
      return eventArgs.OutputParamsList; 
    }
  }

  private Object executeCommandLock = new Object();
}

Edit:

(перефразируя из комментариев). Вы упомянули, что вы можете обрабатывать все вызовы ExecuteCommand в одном потоке асинхронно. Вы можете сделать это с помощью класса Dispatcher:

http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx

Получить ссылку на диспетчер в одном потоке. Передайте эту ссылку другим потокам. Когда эти потоки хотят вызвать ExecuteCommand, они используют dispatcher.BeginInvoke. Поскольку они используют BeginInvoke, все вызовы ExecuteCommand будут работать асинхронно, а не блокироваться в этом потоке. Однако каждая версия ExecuteCommand будет поставлена ​​в очередь и будет последовательно запускать поток диспетчера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...