Pregunta

I've got a GUI interface which has a start and a cancel button. After starting, the main thread which is the GUI thread, is creating a second thread which will do the actual work. When pressing the cancel button, all it does is set a boolean value which tells the working thread to stop its work and end. The problem is that the main GUI thread remain stuck even though I'm sure that the working thread has finished what it was doing. Why is that?

Here is some of the code:

    private Thread workerThread;
    private SomeClass fs;

    private void buttonSearch_Click(object sender, EventArgs e)
    {
      //do some initializations
      fs = new SomeClass();
      workerThread = new Thread(fs.WorkMethod);
      workerThread.Start();
    }

    private void buttonCancel_Click(object sender, EventArgs e)
    {
         fs.StopWork();
         workerThread.Join();
    }


    inside SomeClass:

    private bool keepWorking;

    public void StopWork()
    {
        keepWorking= false;
    }

    public void WorkMethod()
    {
       if (keepWorking)
        {
            //do some stuff with recursion
         }
    }

does someone know why won't the main thread wake up after calling join? I have also tried debugging to see what happens if I change the keepWorking variable to false manually and the method does reach its' end.

¿Fue útil?

Solución

Your WorkMethod has a call to Invoke in there that is invoking a delegate to run on the UI thread and then block until it finishes. Since your UI thread is currently blocking on the call to Join waiting for the background thread, the UI thread is unable to call that delegate.

You now have both threads each waiting on the other, and no progress is being made. This is called a "deadlock".

Also, keepWorking should be marked as volatile as it's being accessed from multiple threads; as it stands the background thread can be accessing an outdated/cached value of that variable for quite some time after the main thread changes it. Marking it as volatile prevents the runtime from making such optimizations.

The solution here is to not block the UI thread with a call to Join. If you need to have some code execute when the background thread ends then you'll need to asynchronously fire that code when the thread finishes instead of synchronously blocking.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top