Параметры потоковой передачи для долго выполняющегося процесса

#c# #winforms #multithreading #.net-3.5

#c# #winforms #многопоточность #.net-3.5

Вопрос:

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

Я хотел бы разрешить пользователю отменить процесс. Мне не нужно, чтобы процесс сообщал о своем прогрессе, только о том, что он завершен или произошла ошибка. Очистка не требуется, если процесс отменен.

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

Использование C # 3.5 Winform.

Комментарии:

1. если у вас нет контроля над кодом, как вы его загружаете? Я спрашиваю, потому что вы потенциально можете создать отдельный процесс.

Ответ №1:

На самом деле отдельный домен приложения или процесс — единственный безопасный способ отменить его. Нитки.Abort () очень небезопасен, это не рекомендуется.

Комментарии:

1. Я действительно видел это с использованием Thread. Abort () может вызвать проблемы, поэтому я планировал избежать этого. Я посмотрю на использование процесса и, по крайней мере, попробую использовать AppDomain. Спасибо.

2. Да, я использовал AppDomain, и, похоже, он будет работать нормально. Я бы поставил вам балл, если бы мог.

Ответ №2:

Есть поток.Abort(), но это не гарантирует завершение потока. Что это делает, так это вызывает исключение ThreadAbortException в потоке, которое не обязательно приведет к завершению потока в зависимости от того, что он делает, например, блок finally {} .

Всегда лучше установить какой-нибудь флаг сотрудничества, который поток проверяет, изящно очищает и завершает работу, увидев, но если у вас нет выбора, Thread.Abort() — это примерно то же самое. Имейте в виду, что если код потока устанавливает блокировки и тому подобное, они не будут очищены, если у потока нет логики для обработки исключения ThreadAbortException и их очистки.

Ответ №3:

Объявите флаг в вашем потоке (например, bool killme) и установите для него значение false. И взгляните на таймер в системе.Потоковая передача для опроса значения этого флага. Если true, выйдите из потока. Этот таймер должен быть создан потоком во время его инициализации.

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

Комментарии:

1. По ссылке показано, как объявить таймер. Используйте это при инициализации вашего потока.

Ответ №4:

Если вы запускаете свой процесс в отдельном потоке, который вы запустили, вы могли бы вызвать Thread.Прервать его. Есть МНОГО причин, почему Thread.Прерывание не следует использовать, поэтому внимательно прочитайте предупреждения.

Ответ №5:

Быстрый и грязный способ — использовать ядро и вызов платформы.

  [System.Runtime.InteropServices.DllImport("kernel32.dll")]
  static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);

 [System.Runtime.InteropServices.DllImport("kernel32.dll")]
  static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);
  

Получите указатель из OpenThread и используйте его в TerminateThread. Вам нужно будет использовать ThreadId из вашего потока в качестве последнего аргумента для OpenThread.

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

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

http://memmove.blogspot.com/2011/04/treating-thread-as-service.html