Я столкнулся с проблемой связи между потоками в приложении С#.NET. Надеюсь, кто-то направит меня в правильном направлении о возможных решениях.
У меня есть приложение на С#.NET. Это приложение формы Windows. Мое приложение имеет два потока: один поток является основным потоком (поток пользовательского интерфейса), а другой - дочерним потоком. Давайте назовем дочерний поток «workerThread». В приложении используется только одна форма. Назовем эту форму «MainForm».
Дочерний поток запускается при загрузке MainForm (используется обработчик события «Load» формы для запуска потока)
В классе MainForm у меня есть переменная с именем «stopWork», которая является общедоступной логической переменной и служит флагом, указывающим, должен ли дочерний поток продолжать работу или должен остановиться.
У меня есть другой класс (помимо класса MainForm), который содержит метод, который я выполняю в дочернем потоке. Давайте назовем этот второй класс «WorkerClass». Я передаю ссылку на текущую форму (MainForm) в конструктор "WorkerClass"
У меня есть кнопка «стоп» в основной форме, которая устанавливает для «stopWork» значение «true», если она нажата, а затем вызывает «workerThread.Join()», чтобы дождаться завершения выполнения дочернего потока.
В дочернем потоке метод "doWork" продолжает проверять состояние "parentForm.stopWork" внутри цикла for. Если для «stopWork» установлено значение «true», цикл прерывается, а затем метод завершается.
Теперь проблема в том, что как только я нажимаю кнопку «Стоп», приложение зависает.
Я вставляю части кода ниже, чтобы его было легче понять:
public partial class MainForm : Form
{
Thread workerThread = null;
ThreadStart workerThreadStart = null;
WorkerClass workerClass = null;
public bool stopWork = true;
/*.......... some code ............*/
private void MainForm_Load(object sender, EventArgs e)
{
workerThreadStart = new ThreadStart(startWork);
workerThread = new Thread(workerThreadStart);
stopWork = false;
workerThread.Start();
}
private void startWork()
{
workerClass = new WorkerClass(this);
}
private void buttonStop_Click(object sender, EventArgs e) //"stop" button
{
if (workerThread != null)
{
if (workerThread.IsAlive == true)
{
stopWork = true;
workerThread.Join();
}
}
}
/*.......... some more code ............*/
}
public class WorkerClass
{
MainForm parentForm=null;
/*......... some variables and code ........*/
public WorkerClass(MainForm parentForm)
{
this.parentForm=parentForm;
}
/* .............. some more code ...........*/
public void doWork()
{
/*.......... some variables and code ...........*/
for(int i=0;i<100000;i++)
{
// ** Here is the check to see if parentForm has set stopWork to true **
if(parentForm.stopWork==true)
break;
/*......... do some work in the loop ..........*/
}
}
/********* and more code .........*/
}
Думаю, я знаю, в чем проблема. Проблема заключается в методе «doWork» в дочернем потоке, пытающемся получить доступ к переменной «stopWork» в родительской форме, когда родительская форма уже заблокирована путем вызова метода «workerThread.Join()». Итак, я думаю, что это проблема "тупика".
Я правильно определил проблему? Или я ошибаюсь и проблема в другом?
В случае, если это действительно тупик, каковы возможные решения для решения этой проблемы?
Я немного погуглил и нашел много ресурсов о синхронизации потоков и о том, как избежать взаимоблокировок. Но я не мог понять, как применить их конкретно к моей проблеме.
Буду очень признателен за любую помощь или рекомендации по решению этой проблемы.