using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ParTask
{
// базовый класс задачи
public class Task
{
// поток, связанный с задачей
public Thread taskThread;
// флаг завершения задачи
public bool finished = false;
// событие синхронизации завершения задач
protected AutoResetEvent taskJoinEvent;
// статический объект синхронизации критических областей
protected static object locker = new object();
// имя задачи, запустившей данную
public string parentTask = null;
// массив конкурирующих задач, завершающихся одновременно с данной
public Task[] concurTasks = null;
// массив задач, запускаемых данной
public Task[] nextTasks = null;
// результат выполнения задачи
public object result = null;
// делегат, использующийся для запуска колбэк-метода вывода протокола
protected LogCallback log;
// делегат, использующийся для запуска колбэк-метода вывода прогресса выполнения задачи
protected ProgressCallback progress;
// задержка циклических операций (мс) для отображения прогресса
protected int lag = 1;
// конструктор
public Task(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag)
{
taskJoinEvent = joinEvent;
log = logCallback;
progress = progressCallback;
lag = opLag;
}
// функция, выполняемая в потоке
public void ThreadProc(object obj)
{
PreTask();
WorkTask(obj);
PostTask();
}
// пролог задачи
protected void PreTask()
{
// вывод времени начала выполнения задачи
DateTime time = DateTime.Now;
log(String.Format("Время начала выполнения задачи {0}: {1}", taskThread.Name, time.ToString("dd.MM.yyyy HH:mm:ss.ffff")));
// вывод имени задачи, активизировавшей данную
if (parentTask == null)
parentTask = "'Главный поток'";
log(String.Format("Задача {0} запущена задачей {1}", taskThread.Name, parentTask));
}
// тело задачи
protected virtual void WorkTask(object obj) { }
// эпилог задачи
protected void PostTask()
{
// определение факта, является данная задача последней по времени
// по сравнению с параллельной задачей, с возможной активизацией следующей
// и соответствующими выводами в общее поле.
// флаг завершения всех конкурентных задач
bool allDone = true;
if (concurTasks != null)
{
lock (locker)
{
for (int i = 0; i < concurTasks.Length; i++)
if (!concurTasks[i].finished)
{
allDone = false;
break;
}
}
}
if (!allDone)
{
lock (locker)
{
// вывод времени окончания выполнения задачи
DateTime time = DateTime.Now;
log(String.Format("Время окончания выполнения задачи {0}: {1}", taskThread.Name, time.ToString("dd.MM.yyyy HH:mm:ss.ffff")));
finished = true;
}
// ожидание завершения конкурентных задач
taskJoinEvent.WaitOne();
}
else
lock (locker)
{
// сбор результатов конкурентных задач
if (concurTasks != null)
{
// сортированный словарь задач включая данную
SortedDictionary<string, object> results = new SortedDictionary<string, object>();
results[taskThread.Name] = this.result;
for (int i = 0; i < concurTasks.Length; i++)
results[concurTasks[i].taskThread.Name] = concurTasks[i].result;
// объединение результатов задач
result = results.Values.ToArray();
}
if (nextTasks != null)
for (int i = 0; i < nextTasks.Length; i++)
{
// установка данной как родительской задачи
nextTasks[i].parentTask = taskThread.Name;
// запуск очередной следующей задачи
nextTasks[i].taskThread.Start(result);
// вывод имени задачи, активизированной данной
log(String.Format("Задача {0} запустила задачу {1}", taskThread.Name, nextTasks[i].taskThread.Name));
}
// вывод времени окончания выполнения задачи
DateTime time = DateTime.Now;
log(String.Format("Время окончания выполнения задачи {0}: {1}", taskThread.Name, time.ToString("dd.MM.yyyy HH:mm:ss.ffff")));
finished = true;
// освобождение закончившихся раньше конкурентных задач
taskJoinEvent.Set();
}
}
}
// делегат, определяющий сигнатуру метода вывода протокола
public delegate void LogCallback(string text);
// делегат, определяющий сигнатуру метода вывода прогресса выполнения задачи
public delegate void ProgressCallback(string taskName, int progress);
// класс задачи A
public class TaskA : Task
{
// конструктор
public TaskA(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int N = (int)obj;
result = f0(N);
}
// функция задачи
private object[] f0(int N)
{
// Массив M1
int[] M1 = new int[N];
// Массив M2
bool[] M2 = new bool[N];
Random rand = new Random(10);
// генерация массивов
for (int i = 0; i < N; i++)
{
M1[i] = rand.Next(1, 201);
M2[i] = rand.Next(0, 2) == 0 ? false : true;
// вывод прогресса
progress(taskThread.Name, 100 / N * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M1:{{{1}}}; Массив M2:{{{2}}}", taskThread.Name, String.Join(",", M1), String.Join(",", M2)));
// возврат результата
return new object[] { M1, M2 };
}
}
// класс задачи B
public class TaskB : Task
{
// конструктор
public TaskB(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M1 = (int[])((object[])obj)[0];
bool[] M2 = (bool[])((object[])obj)[1];
result = f1(M1, M2);
}
// функция задачи
private object f1(int[] M1, bool[] M2)
{
int[] M3 = new int[M1.Length];
// фильтрация массива M1
for (int i = 0; i < M1.Length; i++)
{
if (M2[i] == true)
M3[i] = M1[i];
else
M3[i] = 0;
// вывод прогресса
progress(taskThread.Name, 100 / M1.Length * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M3:{{{1}}}", taskThread.Name, String.Join(",", M3)));
// возврат результата
return M3;
}
}
// класс задачи C
public class TaskC : Task
{
// конструктор
public TaskC(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M1 = (int[])((object[])obj)[0];
bool[] M2 = (bool[])((object[])obj)[1];
result = f2(M1, M2);
}
// функция задачи
private object f2(int[] M1, bool[] M2)
{
int[] M4 = new int[M1.Length];
// фильтрация массива M1
for (int i = 0; i < M1.Length; i++)
{
if (M2[i] == false)
M4[i] = M1[i];
else
M4[i] = 0;
// вывод прогресса
progress(taskThread.Name, 100 / M1.Length * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M4:{{{1}}}", taskThread.Name, String.Join(",", M4)));
// возврат результата
return M4;
}
}
// класс задачи D
public class TaskD : Task
{
// конструктор
public TaskD(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M1 = (int[])((object[])obj)[0];
bool[] M2 = (bool[])((object[])obj)[1];
result = f3(M1, M2);
}
// функция задачи
private object[] f3(int[] M1, bool[] M2)
{
// нахождение среднего арифметического элементов массива M1
int avg = 0;
for (int i = 0; i < M1.Length; i++)
{
avg += M1[i];
// вывод прогресса
progress(taskThread.Name, 100 / M1.Length * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
avg /= M1.Length;
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M1:{{{1}}}; Ср.арифм.(M1): {2}", taskThread.Name, String.Join(",", M1), avg));
// возврат результата
return new object[] { M1, avg };
}
}
// класс задачи E
public class TaskE : Task
{
// конструктор
public TaskE(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M3 = (int[])((object[])obj)[0];
int[] M4 = (int[])((object[])obj)[1];
result = f4(M3, M4);
}
// функция задачи
private object[] f4(int[] M3, int[] M4)
{
int countM3 = 0, countM4 = 0;
int avgM3 = 0, avgM4 = 0;
// нахождение среднего арифметического элементов массивов M3 и M4
for (int i = 0; i < M3.Length; i++)
{
if (M3[i] != 0)
{
avgM3 += M3[i];
countM3++;
}
if (M4[i] != 0)
{
avgM4 += M4[i];
countM4++;
}
// вывод прогресса
progress(taskThread.Name, 100 / M3.Length * i / 2);
// задержка выполнения потока
Thread.Sleep(lag);
}
avgM3 /= countM3;
avgM4 /= countM4;
int[] M5 = new int[M3.Length];
int[] M6 = new int[M3.Length];
// усреднение элементов массивов M3 и M4
for (int i = 0; i < M3.Length; i++)
{
if (M3[i] != 0)
M5[i] = M3[i] - avgM3;
else
M5[i] = 0;
if (M4[i] != 0)
M6[i] = M4[i] - avgM4;
else
M6[i] = 0;
// вывод прогресса
progress(taskThread.Name, 100 / M3.Length * i / 2 + 50);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M5:{{{1}}}; Массив M6:{{{2}}}", taskThread.Name, String.Join(",", M5), String.Join(",", M6)));
// возврат результата
return new object[] { M5, M6 };
}
}
// класс задачи F
public class TaskF : Task
{
// конструктор
public TaskF(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M3 = (int[])((object[])obj)[0];
int[] M4 = (int[])((object[])obj)[1];
result = f5(M3, M4);
}
// функция задачи
private object[] f5(int[] M3, int[] M4)
{
int[] M7 = new int[M3.Length];
int[] M8 = new int[M3.Length];
// "сжатие" массивов M3 и M4
int iM7 = 0, iM8 = 0;
for (int i = 0; i < M3.Length; i++)
{
if (M3[i] != 0)
{
M7[iM7] = M3[i];
iM7++;
}
if (M4[i] != 0)
{
M8[iM8] = M4[i];
iM8++;
}
// вывод прогресса
progress(taskThread.Name, 100 / M3.Length * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M7:{{{1}}}; Массив M8:{{{2}}}", taskThread.Name, String.Join(",", M7), String.Join(",", M8)));
// возврат результата
return new object[] { M7, M8 };
}
}
// класс задачи G
public class TaskG : Task
{
// конструктор
public TaskG(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M7 = (int[])((object[])obj)[0];
int[] M8 = (int[])((object[])obj)[1];
result = f6(M7, M8);
}
// функция задачи
private object[] f6(int[] M7, int[] M8)
{
int positiveTrueCount = 0, negativeFalseCount = 0;
for (int i = 0; i < M7.Length; i++)
{
if (M7[i] > 0)
positiveTrueCount++;
if (M8[i] > 0)
negativeFalseCount++;
// вывод прогресса
progress(taskThread.Name, 100 / M7.Length * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M7:{{{1}}}; Массив M8:{{{2}}}; |M7[i]>0|: {3}; |M8[i]<0|: {4}", taskThread.Name, String.Join(",", M7), String.Join(",", M8), positiveTrueCount, negativeFalseCount));
// возврат результата
return new object[] { M7, M8, positiveTrueCount, negativeFalseCount };
}
}
// класс задачи H
public class TaskH : Task
{
// конструктор
public TaskH(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M1 = (int[])((object[])obj)[0];
int avg = (int)((object[])obj)[1];
result = f7(M1, avg);
}
// функция задачи
private object f7(int[] M1, int avg)
{
int[] M9 = new int[M1.Length];
// усреднение элементов массива M1 по ср. арифм. avg
for (int i = 0; i < M1.Length; i++)
{
M9[i] = M1[i] - avg;
// вывод прогресса
progress(taskThread.Name, 100 / M1.Length * i / 2);
// задержка выполнения потока
Thread.Sleep(lag);
}
// поиск среднего отклонения от среднего арифметического
int deltaAvg = 0;
for (int i = 0; i < M9.Length; i++)
{
deltaAvg += M9[i];
// вывод прогресса
progress(taskThread.Name, 100 / M1.Length * i / 2 + 50);
// задержка выполнения потока
Thread.Sleep(lag);
}
deltaAvg /= M9.Length;
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Среднее отклонение от ср.арифм в M1: {1}", taskThread.Name, deltaAvg));
// возврат результата
return deltaAvg;
}
}
// класс задачи K
public class TaskK : Task
{
// конструктор
public TaskK(AutoResetEvent joinEvent, LogCallback logCallback, ProgressCallback progressCallback, int opLag) : base(joinEvent, logCallback, progressCallback, opLag) { }
// тело задачи
protected override void WorkTask(object obj)
{
// определение значения функции задачи (с отображением динамики выполнения задачи)
int[] M5 = (int[])((object[])((object[])obj)[0])[0];
int[] M6 = (int[])((object[])((object[])obj)[0])[1];
int[] M7 = (int[])((object[])((object[])obj)[1])[0];
int[] M8 = (int[])((object[])((object[])obj)[1])[1];
int positiveTrueCount = (int)((object[])((object[])obj)[1])[2];
int negativeFalseCount = (int)((object[])((object[])obj)[1])[3];
int deltaAvg = (int)((object[])obj)[2];
result = f8(M5, M6, M7, M8, positiveTrueCount, negativeFalseCount, deltaAvg);
}
// функция задачи
private object f8(int[] M5, int[] M6, int[] M7, int[] M8, int positiveTrueCount, int negativeFalseCount, int deltaAvg)
{
int[] M10 = new int[M5.Length];
// формирование массива отфильтрованных данных
for (int i = 0; i < M5.Length; i++)
{
M10[i] = (M7[i] - M5[i]) / positiveTrueCount + (M8[i] - M6[i]) / negativeFalseCount + deltaAvg;
// вывод прогресса
progress(taskThread.Name, 100 / M5.Length * i);
// задержка выполнения потока
Thread.Sleep(lag);
}
progress(taskThread.Name, 100);
// вывод результата выполнения задачи
log(String.Format("Результат выполнения задачи {0}. Массив M10:{{{1}}}", taskThread.Name, String.Join(",", M10)));
// возврат результата
return M10;
}
}
}