Как узнать, завершено ли выполнение потока, не опрашивая ThreadState?

Есть ли элегантный способ узнать, когда рабочий поток завершен, чтобы я мог получить доступ к созданным им ресурсам?

Например, если рабочий поток запросил список серверов SQL, используя

ServersSqlDataSourceEnumerator.Instance.GetDataSources();

и сохранил результат в переменной DataTable, какой механизм я могу использовать, чтобы узнать, когда эта переменная DataTable была заполнена/доступна. Я не хочу опрашивать ThreadState; было бы идеально запустить событие, когда оно будет сделано, чтобы я мог выполнять действия с результатом.

Спасибо!


person Mark Carpenter    schedule 03.06.2009    source источник


Ответы (5)


Вы можете использовать механизм обратного вызова или блокировать событие, чтобы узнать о завершении асинхронной операции. См. эту страницу для Модели асинхронного программирования в .net — вы можете вызвать BeginInvoke для любого делегата, чтобы выполнить действие асинхронно.

Если вы используете тип BackgroundWorker, вы можете подписаться на событие RunWorkerCompleted.

person Gishu    schedule 03.06.2009
comment
+1 Ой, очень красиво! Я сейчас просматриваю ссылку на модель асинхронного программирования и, возможно, смогу использовать один из перечисленных там примеров. Спасибо!! - person Mark Carpenter; 03.06.2009

Итак, запустите событие :-P

Вы также можете использовать AutoResetEvent:
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

person Joel Martinez    schedule 03.06.2009
comment
Это потребует какого-то опроса, которого я пытаюсь избежать. Я ищу решение, которое инкапсулирует создание, выполнение и уведомление о завершении потока. Возможность прервать поток также является необходимостью. - person Mark Carpenter; 03.06.2009

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

E.g.

private void SetWorkerThreadToDoWork()
{
  WorkerThread.Start();
}

private void MyWorkerThreadWork()
{
  //This will be on the WorkerThread (called from WorkerThread.Start())
  DoWorkFunc();
  WorkComplete();
}

private void WorkComplete()
{
  if(InvokeRequired == true)
  {
    //Do the invoke
  }
  else
  {
  //Check work done by worker thread
  //e.g. ServersSqlDataSourceEnumerator.Instance.GetDataSources();
  }
}

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

person Lloyd Powell    schedule 03.06.2009

Вы можете проверить мой ответ в этом треке SO

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

Используйте аналогичный подход, чтобы получать уведомления о выполнении асинхронной операции.

Надеюсь это поможет :)

person SO User    schedule 03.06.2009

Я не программирую на C#, но вот что я сделал с Delphi, возможно, вы сможете сделать это и с C#. У меня есть потомок TThread, и в событии «уничтожить» я отправляю сообщение его создателю: «Эй, я скоро умру!». Таким образом, его родитель (который является основным потоком) создает новый, если ему нужен новый. Если быть точным, он запускает таймер, который при срабатывании создает новый поток, если новый необходим (сайты отстойные (смеется)!!).

person Olivier Pons    schedule 03.06.2009