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

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

Помещение в поток нескольких функции

В отдельный поток можно помещать несколько функций, указав их во внутреннем списке объекта-делегата ThreadStart. При обычном выполнении приложения происходит то же самое - все функции выполняются в одном потоке. А здесь мы часть функций сами размещаем в отдельном потоке, используя делегат стандартным способом. Обратите внимание, что делегат может адресовать только функции с пустой сигнатурой и без возвращаемого значения, поскольку объявлен в библиотеке так

public delegate void ThreadStart();

Приведем пример

using System;
using System.Threading;
    
namespace Test
{
    class MyClass
    {
        // Открытые поля с маркерами потоков для упрощения кода
        public int mBase, mFunc1, mFunc2;
    
        // Конструктор исполняется в основном потоке
        public MyClass()
        {
            // Извлекаем маркер текущего потока
            mBase = Thread.CurrentThread.GetHashCode();
    
            // Создаем делегат со ссылками на две функции
            ThreadStart del = new ThreadStart(Func1); 
            del += Func2;
            Thread th = new Thread(del); // Создаем поток     
            th.Start();                  // Выполнить функции
        }
    
        // Метод будет исполняться в дополнительном потоке
        private void Func1()
        {
            // Извлекаем маркер текущего потока
            mFunc1 = Thread.CurrentThread.GetHashCode();
        }
    
        // Этот метод также будет исполняться в дополнительном потоке
        private void Func2()
        {
            // Извлекаем маркер текущего потока
            mFunc2 = Thread.CurrentThread.GetHashCode();
        }
    }
    
    // Класс с точкой входа
    class Program
    {
        // Исполняется в основном потоке
        static void Main()
        {
            // Настройка консоли
            Console.Title = "Помещение в поток 
		нескольких функции";
            Console.ForegroundColor = ConsoleColor.White;
            Console.CursorVisible = false;
            Console.WindowWidth = 39;
            Console.WindowHeight = 5;
    
            MyClass obj = new MyClass();// Исполняем
    
            // Показываем маркеры
            Console.WriteLine("Поток выполнения 
		метода MyClass(): " + obj.mBase);
            Console.WriteLine("Поток выполнения 
		метода Func1(): " + obj.mFunc1);
            Console.WriteLine("Поток выполнения 
		метода Func2(): " + obj.mFunc2);
            Console.WriteLine("Поток выполнения 
		метода Main(): " +  Thread.CurrentThread.GetHashCode());
    
            Console.ReadLine(); // Ждем нажатия клавиши Enter
        }
    }
}
Листинг 11.5 . Помещение в поток нескольких функции

Уничтожение потока

Для уничтожения потока применяется метод Abort(), который может использоваться как без параметра, так и с параметром типа Object. При использовании метода Abort() с параметром в параметре можно разместить любую информацию. Метод Abort() инициирует выброс исключения типа ThreadAbortException, в экземпляр которого будет помещена эта информация. Это исключение надо обрабатывать, иначе будет выброшено необработанное системное исключение. При вызове метода Abort() свойство состояния потока System.Threading.Thread.ThreadState устанавливается в значение одноименного перечисления System.Threading.ThreadState.AbortRequested.

При попытке уничтожения потока его работа немедленно прерывается на выполнении текущей команды. Но если поток в это время выполнял команды неуправляемого кода, например, обращался к некоторой системной функции или внешнему COM -объекту, то среда CRL дождется возвращения потока в управляемую область и сразу прервет его. Возобновить работу потока можно с помощью статического метода Thread. ResetAbort(), но в этом случае поток начнет выполняться не с прерванного состояния, а будет запущен заново.

Вот код приложения, которое прерывает само себя, уничтожая основной поток, в который оно автоматически загружается.

using System;
using System.Threading;
    
namespace Test
{
    class MyClass
    {
        // Конструктор исполняется в основном потоке
        public MyClass()
        {
            // Основной поток существует, попытаемся его прервать 
            // через защищенный блок кода, чтобы отловить исключение
            try
            {
                Thread.CurrentThread.Abort();
            }
            catch (ThreadAbortException e)
            {
                Console.WriteLine("Выброшено 
			исключение ThreadAbortException\n" +
                    "Сообщение: {0}", e.Message);
                Console.WriteLine("\nНажмите Enter, 
			чтобы завершить основной поток...");
    
                Console.ReadLine();
            }
        }
    }
    
    // Класс с точкой входа
    class Program
    {
        // Исполняется в основном потоке
        static void Main()
        {
            // Настройка консоли
            Console.Title = "Уничтожение основного потока";
            Console.ForegroundColor = ConsoleColor.White;
            Console.CursorVisible = false;
            Console.WindowWidth = 49;
            Console.WindowHeight = 5;
    
            new MyClass();// Исполняем и прерываем
                
            // Исполнение до сих пор не дойдет, прервется в конструкторе
            Console.ReadLine(); 
        }
    }
}
Листинг 11.6 . Приложение, прерывающее само себя через основной поток

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

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

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

 

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

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