С# Потоки. Mutex
Первый поток генерирует случайным образом числа и записывает их в файл.
Второй поток ждет, когда первый закончит свою работу. Затем анализирует содержимое файла (который создал первый поток) и создает новый файл, в котором будут собраны простые числа.
Третий поток ожидает, когда закончит свою работу второй поток, и потом анализирует содержимое файла (который создал второй поток). Затем он создает новый файл, в котором будут собраны числа, заканчивающиеся на 7. При реализации должен использоваться механизм мьютексов
Проблема у меня в том, что у меня как-то непредсказуемо запускаются потоки (проще говоря, не в том порядке), а бывает, что все ОК (в общем, через раз). Хотя я запускаю необходимые команды mutex.WaitOne(); mutex.ReleaseMutex(); Что я делаю нет так?
Код прилагаю. Вспомогательный класс Worker, где происходит вся "магия"
public class Worker
{
private string[] fileNames = { "Thread1.txt", "Thread2.txt", "Thread3.txt" };
private Mutex mutex;
Random random = new Random();
//public static List<Report> reports { get; private set; }
public Worker()
{
mutex = new Mutex();
}
public void Start(object numberOperation)
{
mutex.WaitOne();
WorkBegin(Thread.CurrentThread.Name + " начал свою работу");
Thread.Sleep(3000);
switch ((int)numberOperation)
{
case 0: WorkBegin(Thread.CurrentThread.Name + " генерирует файл");
using (StreamWriter writer = new StreamWriter(fileNames[0], false))
{
for (int i = 0; i < 100000; i++)
{
int number1 = random.Next(1000);
writer.WriteLine(number1.ToString());
}
}
break;
case 1: WorkBegin(Thread.CurrentThread.Name + " ReadWritePrimeNumberToFile");
using (StreamWriter writer = new StreamWriter(fileNames[1], false))
{
using (StreamReader reader = new StreamReader(fileNames[0]))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (ulong.TryParse(line, out ulong number) & checkPrimeNumber(number))
{
writer.WriteLine(number.ToString());
}
}
}
}
break;
case 2: WorkBegin(Thread.CurrentThread.Name + " ReadWritePrimeNumberToFile");
using (StreamWriter writer = new StreamWriter(fileNames[2], false))
{
using (StreamReader reader = new StreamReader(fileNames[1]))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line[line.Length - 1] == '7')
{
writer.WriteLine(line);
}
}
}
}
break;
}
WorkEnd(Thread.CurrentThread.Name + " завершил свою работу");
mutex.ReleaseMutex();
}
//Функция проверки является ли число простым
private bool checkPrimeNumber(ulong number)
{
if (number < 2)
return false;
for (ulong i = 2; i < number; i++)
{
if (number % i == 0)
{
return false;
}
}
return true;
}
public event Action<string> WorkBegin;
public event Action<string> WorkEnd;
}
Основной класс:
private string[] nameThread = { "Процесс заполнения файла числами", "Процесс перебора простых чисел", "Процесс перебора простых чисел по условию (7 на конце)" };
public FormMain()
{
InitializeComponent();
buttonStart.Click += ButtonStart_Click;
buttonReportShow.Click += ButtonReportShow_Click;
}
private void ButtonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
Worker worker = new Worker();
worker.WorkBegin += Worker_WorkBegin;
worker.WorkEnd += Worker_WorkEnd;
Thread[] threads = new Thread[nameThread.Length];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(worker.Start);
threads[i].Name = nameThread[i];
threads[i].Start(i);
}
}
private void Worker_WorkBegin(string info)
{
Action action = () => { listBoxLog.Items.Add(info); };
this.InvokeEx(action);
}
private void Worker_WorkEnd(string info)
{
Action action = () => { listBoxLog.Items.Add(info); };
this.InvokeEx(action);
}
Класс ControlHelper
public static class ControlHelper
{
public static void InvokeEx(this Control control, Action action)
{
if (control.InvokeRequired)
control?.Invoke(action);
else
action();
}
}