Шаг 249.
Язык программирования C#. Начала.
Многопоточное программирование. Примеры использования
На этом шаге мы рассмотрим несколько примеров решения задач, в которых используется обработка исключений.
Здесь мы рассмотрим несколько программ, в которых используются рассмотренная на предыдущих шагах обработка исключений.
Задание 1.
Напишите программу, в которой два потока заполняют целочисленный массив. Один поток заполняет массив с начала до конца числами, являющимися степенями двойки (20,
21, 22 и так далее). Другой поток заполняет массив с конца до начала числами, являющимися степенями тройки (30, 31, 32 и так далее).
Раскрыть/скрыть решение и комментарии.
Текст программы аналогичен примеру, приведенному на 244 шаге. Надеемся, что приведенных комментариев будет достаточно для понимания принципов ее работы.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace pr249_1
{
class Program
{
// Главный метод:
static void Main()
{
// Размер массива:
int size = 20;
// Создание массива:
int[] ch = new int[size];
// Заполнение массива нулями:
for (int k = 0; k < ch.Length; k++)
{
ch[k] = 0;
Console.Write("|" + ch[k]);
}
Console.WriteLine("|");
// Индекс первого и последнего элемента в массиве:
int first = 0, second = ch.Length - 1;
// Объектные переменные для потоков:
Thread A, B;
// Создание объекта для первого потока:
A = new Thread(() =>
{
// Начальный символ для заполнения массива:
int start = 1;
// Бесконечный цикл:
while (true)
{
// Если второй индекс больше первого индекса:
if (second > first)
{
// Значение элемента:
ch[second] = start;
// Новый символ для присваивания:
start *= 3;
// Новое значение индекса:
second--;
// Задержка в выполнении потока:
Thread.Sleep(100);
}
// Если второй индекс не больше первого:
else
{
// Завершение в выполнении потока:
Thread.CurrentThread.Abort();
}
}
});
// Создание объекта для второго потока:
B = new Thread(() =>
{
// Начальный символ для заполнения массива:
int start = 1;
// Бесконечный цикл:
while (true)
{
// Если первый индекс меньше второго:
if (first < second)
{
// Значение элемента:
ch[first] = start;
// Новый символ для присваивания:
start *= 2;
// Новое значение индекса:
first++;
// Задержка в выполнении потока:
Thread.Sleep(100);
}
// Если первый индекс не меньше второго:
else
{
// Завершение выполнения потока:
Thread.CurrentThread.Abort();
}
}
});
// Запуск первого потока на выполнение:
A.Start();
// Запуск второго потока на выполнение:
B.Start();
// Ожидание выполнения первого потока:
if (A.IsAlive) A.Join();
// Ожидание выполнения второго потока:
if (B.IsAlive) B.Join();
// Отображение содержимого массива:
for (int k = 0; k < ch.Length; k++)
{
Console.Write("|" + ch[k]);
}
Console.WriteLine("|");
}
}
}
Архив проекта можно взять
здесь.
Результат работы приложения может быть таким:
Рис.1. Результат работы приложения
Задание 2.
Напишите программу, в которой создается двумерный целочисленный массив. Массив заполняется построчно: первая строка заполняется числами, являющимися степенями двойки (2
0,
2
1, 2
2 и так далее), вторая строка заполняется степенями тройки (3
0, 3
1, 3
2 и так далее), и так далее. Для заполнения каждой
строки запускается дочерний поток. Объектные переменные для потоков следует организовать в виде массива.
Раскрыть/скрыть решение и комментарии.
Решение этой задачи аналогично примеру, приведенному на 245 шаге. Приведем текст программы, решающей эту задачу.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace pr249_2
{
class Program
{
// Главный метод:
static void Main()
{
// Двумерный массив:
int[,] nums = new int[6, 8];
// Массив из объектных переменных для потоков:
Thread[] t = new Thread[nums.GetLength(0)];
// Перебор элементов массива:
for (int i = 0; i < t.Length; i++)
{
// Локальная переменная для цикла:
int p = i;
// Создание объекта потока:
t[i] = new Thread(() =>
{
// Перебор элементов в строке
// целочисленного массива:
nums[p, 0] = p + 1;
for (int j = 1; j < nums.GetLength(1); j++)
{
// Элементу присваивается значение:
nums[p, j] = nums[p, j - 1] * (p + 1);
// Приостановка выполнения потока:
Thread.Sleep(100);
}
});
// Запуск потока на выполнение:
t[i].Start();
}
// Ожидание завершения дочерних потоков:
for (int i = 0; i < t.Length; i++)
{
if (t[i].IsAlive) t[i].Join();
}
// Отображение содержимого двумерного целочисленного
// массива:
for (int i = 0; i < nums.GetLength(0); i++)
{
for (int j = 0; j < nums.GetLength(1); j++)
{
Console.Write("{0,-8}", nums[i, j]);
}
Console.WriteLine();
}
}
}
}
Архив проекта можно взять
здесь.
Результат работы приложения изображен на рисунке 2.
Рис.2. Результат работы приложения
Надеемся, что приведенный текст программы не вызвал затруднений.
Задание 3.
Напишите программу, в которой с помощью дочернего потока вычисляется сумма
("точное" значение для суммы равно
3е2 - 1≈21,167168)
Раскрыть/скрыть решение и комментарии.
За основу решения этой задачи можно взять текст программы, приведенной на 247 шаге. Вот текст программы:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace pr249_3
{
class Program
{
// Главный метод:
static void Main()
{
// Переменная для записи значения суммы:
double s = 0;
Console.WriteLine("Вычисление суммы");
// Контрольное значение для суммы:
Console.WriteLine("Koнтpoльнoe значение: {0}", 3 * Math.E * Math.E - 1);
// Создание объекта потока:
Thread calc = new Thread(() =>
{
// Индексная переменная:
int n = 1;
// Добавка к сумме:
double q = 4;
// Степень двойки:
double sd = 2;
// Бесконечный цикл:
do
{
// Прибавление слагаемого к сумме:
s += q;
// Новое значение для индексной переменной:
n++;
// Новая степень двойки:
sd *= 2;
// Вычисление добавки к сумме
// для следующего цикла:
q = sd * (n + 1);
for (int k = 1; k <= n; k++)
{
q /= k;
}
// Приостановка в выполнении потока:
Thread.Sleep(100);
} while (true);
});
// Запуск потока на выполнение:
calc.Start();
// Приостановка выполнения главного потока:
Thread.Sleep(1000);
// Завершение выполнения дочернего потока:
calc.Abort();
// Отображение результата вычислений:
Console.WriteLine("Вычисленное значение: {0}", s);
}
}
}
Архив проекта можно взять
здесь.
Результат работы приложения приведен на рисунке 3.
Рис.3. Результат работы приложения
Со следующего шага мы начнем знакомиться с многопоточным программированием.
Предыдущий шаг
Содержание
Следующий шаг