Страница 419 из 502
Как следует из приведенного выше результата, значение 100 передается методу Abort() в качестве кода прерывания. Это значение становится затем доступным посредством свойства ExceptionState из класса исключения ThreadAbortException, которое перехватывается потоком при его прерывании.
Запрос на преждевременное прерывание может быть переопределен в самом потоке. Для этого необходимо сначала перехватить в потоке исключение ThreadAbortException, а затем вызвать метод ResetAbort(). Благодаря этому исключается повторное генерирование исключения по завершении обработчика исключения, прерывающего данный поток. Ниже приведена форма объявления метода ResetAbort().
<b>public static void ResetAbort()</b>
Вызов метода ResetAbort() может завершиться неудачно, если в потоке отсутствует надлежащий режим надежной отмены преждевременного прерывания потока.
В приведенном ниже примере программы демонстрируется применение метода ResetAbort().
<b>// Использовать метод ResetAbort().</b>
<b>using System;</b>
<b>using System.Threading;</b>
<b>class MyThread {</b>
<b> public Thread Thrd;</b>
<b> public MyThread(string name) {</b>
<b> Thrd = new Thread(this.Run);</b>
<b> Thrd.Name = name;</b>
<b> Thrd.Start();</b>
<b> }</b>
<b> // Это точка входа в поток,</b>
<b> void Run() {</b>
<b> Console.WriteLine(Thrd.Name + ".начат.");</b>
<b> for (int i = 1; i<=1000; i++) {</b>
<b> try {</b>
<b> Console.Write(i + " ");</b>
<b> if((i %10)==0) {</b>
<b> Console.WriteLine();</b>
<b> Thread.Sleep(250);</b>
<b> }</b>
<b> } catch(ThreadAbortException exc) {</b>
<b> if((int)exc.ExceptionState ==0) {</b>
<b> Console.WriteLine("Прерывание потока отменено! " +</b>
<b> "Код завершения " + exc.ExceptionState);</b>
<b> Thread.ResetAbort();</b>
<b> }</b>
<b> else</b>
<b> Console.WriteLine("Поток прерван, код завершения "</b>
<b> + exc.ExceptionState);</b>
<b> }</b>
<b> }</b>
<b> Console.WriteLine(Thrd.Name + " завершен нормально.");</b>
<b> }</b>
<b>}</b>
<b>class ResetAbort {</b>
<b> static void Main() {</b>
<b> MyThread mt1 = new MyThread("Мой Поток");</b>
<b> Thread.Sleep(1000); // разрешить порожденному потоку начать свое выполнение</b>
<b> Console.WriteLine("Прерывание потока.");</b>
<b> mt1.Thrd.Abort(0); // это не остановит поток</b>
<b> Thread.Sleep(1000); // разрешить порожденному потоку выполняться подольше</b>
<b> Console.WriteLine("Прерывание потока.");</b>
<b> mt1.Thrd.Abort(100); // а это остановит поток</b>
<b> mt1.Thrd.Join(); // ожидать прерывания потока</b>
<b> Console.WriteLine("Основной поток прерван.");</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения этой программы.
<b>Мой Поток.начат.</b>
<b>1 2 3 4 5 6 7 8 9 10</b>
<b>11 12 13 14 15 16 17 18 19 20</b>
<b>21 22 23 24 25 26 27 28 29 30</b>
<b>31 32 33 34 35 36 37 38 39 40</b>
<b>Прерывание потока.</b>
<b>Прерывание потока отменено! Код завершения 0</b>
<b>41 42 43 44 45 46 47 48 49 50</b>
<b>51 52 53 54 55 56 57 58 59 60</b>
<b>61 62 63 64 65 66 67 68 69 70</b>
<b>71 72 73 74 75 76 77 78 79 80</b>
<b>Прерывание потока.</b>
<b>Поток прерван, код завершения 100</b>
<b>Основной поток прерван.</b>
Если в данном примере программы метод Abort() вызывается с нулевым аргументом, то запрос на преждевременное прерывание отменяется потоком, вызывающим метод ResetAbort(), и выполнение этого потока продолжается. Любое другое значение аргумента приведет к прерыванию потока.