Уроки OpenGL + C#.

Базовые методы работы с потоками в C# .NET.

Сейчас мы рассмотрим процесс создания потоков, используя в качестве примера разработку консольной программы. При старте программы будут запускаться на выполнение 4 потока, каждый из которых будет выводить свой номер в окно консоли.

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


При создании потоков мы установим для них различные приоритеты, таким образом, части потоков будет выделяться больше квантов времени процессора, и они будут доминировать при выводе своего номера в окно. Мы сможем это наблюдать в ходе работы программы.

Программа очень проста, так что давайте приступим.


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


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Thread_Step_1
{
class Program
{

static void Main(string[] args)
{
}

}
}


Для работы с потоками нам необходимо подключить пространстве имен System.Threading.

Добавьте строку using System.Threading после строки using System.Text.

Непосредственно перед функцией Main мы добавим функцию WriteString, которая будет отвечать за вывод символов, назначенных данному потоку (мы будем назначать номер потока) на экран. В качестве параметра функция будет получать объект _Data, который впоследствии будет преобразован в сроку в коде функции.

Код функции будет выглядеть следующим образом:

 


static void WriteString(object _Data)
{
//для получения строки используем преобразование типов:
// приводим переменную _Data к типу string и записываем
// в переменную str_for_out
string str_for_out = (string) _Data;
// теперь поток 1 тысячу раз выведит полученную строку (свой номер)
for (int i = 0; i <= 1000; i++)
Console.Write(str_for_out);
}

Теперь перейдем непосредственно к коду функции Main. Здесь мы реализуем следующий код:

  1. Сначала мы создадим 4 потока, каждому из которых укажем, что они будут выполнять функцию WriteString.
  2. Далее мы назначим потокам приоритеты.
  3. После этого мы запустим все четыре потока, передав в качестве параметра их номера.
  4. Далее нам останется только дождаться завершения все четырех потоков и ожидать ввода пользователем какого-либо символа, чтобы завершить выполнение программы.


Код функции Main теперь будет выглядеть следующим образом:


static void Main(string[] args) //точка входа в программу
{
//создаем 4 потока, в качестве параметров передаем имя Выполняемой функции
Thread th_1 = new Thread(WriteString);
Thread th_2 = new Thread(WriteString);
Thread th_3 = new Thread(WriteString);
Thread th_4 = new Thread(WriteString);

//расставляем приоритеты для потоков

th_1.Priority = ThreadPriority.Highest; // самый высокий
th_2.Priority = ThreadPriority.BelowNormal; // выше среднего
th_3.Priority = ThreadPriority.Normal; // средний
th_4.Priority = ThreadPriority.Lowest; // низкий

// запускаем каждый поток, в качестве параметра передаем номер потока

th_1.Start( "1");
th_2.Start( "2");
th_3.Start( "3");
th_4.Start( "4");

Console.WriteLine( "все потоки запущены ");
//Ждем заврешения каждого потока
th_1.Join();
th_2.Join();
th_3.Join();
th_4.Join();

Console.ReadKey(); // прочитать символ (пока пользователь не нажмет клавишу программа не завершиться (чтобы можно было успеть посмотреть результат)).
}


Откомпилируйте и запустите программу (F5).

Пример результата работы программы можно увидеть на рисунке 1.

Так же, необходимо помнить, что при каждом запуске программы, выводимый на экран результат будет отличаться от предыдущего. А если запустить созданное приложение не из среды Visual Studio (без отладки), а просто, из операционной системы, то, до вывода сообщения «Все потоки запущены», по несколько раз может успеть выполнится назначенная функция каждого потока.

Пример выполнения многопоточного консольного приложения.
Рисунок 1.

Как видно из рисунка, к моменту запуска последнего, 4-го потока, 1-й поток, имеющий Highest приоритет уже успел полность выполниться. Последний же, 4-й приоритет, запущеный в добавок еще и последним, выполниться уже безусловно после всех других потоков.

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

Исходный код данного урока (для VS 2008).


Обсуждение данного урока: Многопоточность, работа с потоками в C# .NET
Далее: 4.1 Немного Об OpenGL