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

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

 

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