Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1446 / 158 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Лекция 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. Ввожу код на сайте, пишет:

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

 

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