Опубликован: 25.03.2010 | Уровень: для всех | Доступ: платный
Лекция 11:

Процессы, домены, потоки в C#

Восстановление потока

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

using System;
using System.Threading;
    
namespace Test
{
    class MyClass
    {
        int i = 0; // Счетчик сообщений в общей памяти потоков
    
        // Клиентский код для управления дополнительным потоком
        public MyClass()
        {
            // Создаем дополнительный поток для функции Func()
            ThreadStart del = new ThreadStart(Func);
            Thread th = new Thread(del);
            th.Start(); // Запускаем на выполнение
            // Приостановим основной поток для устранения состязаний
            Thread.Sleep(1000);
    
            // Обследуем запущенный дополнительный поток
            Console.WriteLine("{1}) Запустили Func() 
		в потоке {0}", 
                th.GetHashCode(), ++i);
            Console.WriteLine("{1}) Состояние 
		работающего потока: {0}",
                th.ThreadState.ToString(), ++i);
    
            // Пытаемся прервать самовосстанавливающийся поток
            th.Abort("Основной поток хочет уничтожить!");
            // Приостановим основной поток для устранения состязаний
            Thread.Sleep(1000);
    
            // Восстановленная функция закончила работу
            Console.WriteLine("{1}) Состояние 
		завершенного потока: {0}",
                th.ThreadState.ToString(), ++i);
        }
    
        // Локальная функция, размещаемая в отдельном потоке
        void Func()
        {
            try
            {
                // Эмулируем бурную деятельность, пока не прервут
                for (; ; ) ;
            }
            catch (ThreadAbortException e)
            {
                // Обследуем поток
                Console.WriteLine("{1}) Выброшено 
			исключение {2}\n\t" +
               		"Сообщение: {0}", e.Message, 
			++i, e.GetType().Name);
                Console.WriteLine("{1}) Состояние 
			потока при " +
                    "попытке уничтожения:\n\t{0}",
                    Thread.CurrentThread.ThreadState.ToString(), ++i);
                Console.WriteLine("{1}) Сообщение, 
			переданное " +
                    "через параметр Abort():\n\t{0}",
                    e.ExceptionState.ToString(), ++i);
    
                // Самовосстанавливаемся
                Thread.ResetAbort();
    
                // Обследуем поток
                Console.WriteLine("{1}) Состояние 
			потока после " +
                    "восстановления:\n\t{0}",
                    Thread.CurrentThread.ThreadState.ToString(), ++i);
                Console.WriteLine("{1}) Func() выполняется 
			в потоке {0}",
                    Thread.CurrentThread.GetHashCode(), ++i);
            }
        }
    }
    
    // Класс с точкой входа
    class Program
    {
        // Исполняется в основном потоке
        static void Main()
        {
            // Настройка консоли
            Console.Title = "Попытка уничтожения " +
                "самовосстанавливающегося потока";
            Console.ForegroundColor = ConsoleColor.White;
            Console.CursorVisible = false;
            Console.WindowWidth = 51;
            Console.WindowHeight = 13;
    
            new MyClass();// Исполняем
    
            // Ждем нажатия клавиши Enter
            Console.ReadLine();
        }
    }
}
Листинг 11.7 . Попытка уничтожения самовосстанавливающегося потока

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

Извлечение информации о состоянии потока

Мы уже частично использовали свойство, только для чтения, Thread.ThreadState в предыдущем примере, чтобы узнать, в каком состоянии находится поток. Мы его применяли и к экземпляру th потока во внешнем коде как th.ThreadState.ToString(), и внутри потока как Thread.CurrentThread.ThreadState.ToString(). Значения этого свойства, устанавливаемые одноименным перечислением System.Threading.ThreadState, позволяют контролировать проводимые с потоком манипуляции и определять, в каком состоянии он в данный момент находится, прежде чем применять к нему какие-то действия.

Максим Филатов
Максим Филатов

Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет:

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

 

Как активировать код?

Денис Пашков
Денис Пашков
Россия
Татьяна Ковалюк
Татьяна Ковалюк
Украина, Киев, Киевский политехнический институт, 1974