Возможные способы манипулирования выполнением потока из другого потока? - PullRequest
1 голос
/ 30 сентября 2010

Это вопрос из двух частей .

Первый , допустим, у меня есть функция, выполняющаяся в другом потоке:

private AutoResetEvent StopEvent = new AutoResetEvent( false);

public void WorkerThread()
{
  while( !StopEvent.WaitOne( 10)) {
    a();
    b();
    c();
  }
}

Теперь я хочу приостановить эту тему.Thread.Suspend не может быть и речи, потому что она не может гарантировать мне безблокировочную систему после вызова.Ожидание другого AutoResetEvent также нежелательно, поскольку пауза «гранулярность» будет слишком большой.Я придумала два «решения», но не в восторге ни от одного из них (но на данный момент предпочтительнее № 2):

1) чередование PauseEvent.WaitOne() везде:

private AutoResetEvent StopEvent = new AutoResetEvent( false);
private ManualResetEvent PauseEvent = new ManualResetEvent( true);

public void WorkerThread()
{
  while( !StopEvent.WaitOne( 10)) {
    PauseEvent.WaitOne( 0);
    a();
    PauseEvent.WaitOne( 0);
    b();
    PauseEvent.WaitOne( 0);
    c();
  }
}

2) заставить a (), b () и c () бросить a MyException.Затем я могу подождать в блоке перехвата, пока не появится сигнал нажатия кнопки «возобновить». PauseEvent:

private AutoResetEvent StopEvent = new AutoResetEvent( false);
private AutoResetEvent PauseEvent = new AutoResetEvent( false);

public void WorkerThread()
{
  while( !StopEvent.WaitOne( 10)) {
    try {
      a();
      b();
      c();
    } catch( MyException) {
      PauseEvent.WaitOne(); // wait indefinitely until signaled by another thread
    }
  }
}

(2) действительно кажется единственным способом сделать это, но я хотел бы знать, есть ли у кого-нибудьпопробовал другой метод "паузы".

Во-вторых , часть, на которую я натолкнулся, является хорошим способом для решения №2 вызвать в первую очередь исключение.В настоящее время я в основном инструментировал низкоуровневый код, вызываемый a (), b () и c (), для поиска события, которое должно быть сигнализировано, которое говорит им выбросить MyException.Это единственный способ, которым я знаю, что вы можете вызывать поведение в одном потоке из другого.

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

Ответы [ 2 ]

0 голосов
/ 02 октября 2010

После работы над несколькими различными подходами к этой проблеме, я думаю, у меня есть кое-что, что работает достаточно хорошо.Я в основном пошел с # 2, потому что он использует фундаментальное поведение AutoResetEvent для приостановки и возобновления.

Мои потоки запускают автоматы, которые являются производными от Stateless, поэтому я смог поставить все паузы и возобновитьфункциональность в базовом классе, что делает мой код красивым и чистым.Я также могу иметь специфичные для клиента функциональные возможности, переопределяя методы в производном классе.

В конце концов, были достигнуты компромиссы между гранулярностью приостановки и элегантностью кода.Я пожертвовал гранулярностью, чтобы мне не приходилось переть WaitOne() s повсюду.

0 голосов
/ 30 сентября 2010

Мне не известен подход в стиле микроконтроллера с приоритетными прерываниями в .Net.Но в то же время вы можете захотеть рассмотреть общий флаг, который ваш поток постоянно проверяет, должен ли он остановиться или запустить.Как только он обнаруживает запрос на паузу, он может ждать, используя Thread.Sleep или Timer, чтобы проверить разрешение на запуск.Возможно, не такой элегантный, как вы надеялись, но он предсказуем и прост в реализации.

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