views:

190

answers:

3

I tried the following (pseudocode) but I always get a deadlock when Iam trying to stop my thread. The problem is that Join() waits for the thread to complete and a pending Invoke() operation is also waiting to complete. How can I solve this?

Thread workerThread = new Thread(BackupThreadRunner);
volatile bool cancel;

// this is the thread worker routine
void BackupThreadRunner()       
{
  while (!cancel)
  { 
     DoStuff();
     ReportProgress();
  }
}

// main thread
void ReportProgress()
{
   if (InvokeRequired)
   {
      Invoke(ReportProgress);
   }
   UpdateStatusBarAndStuff();
}

// main thread
void DoCancel()
{
   cancel=true;
   workerThread.Join();
}
+3  A: 

You could use BeginInvoke(ReportProgress) - that way your worker thread doesn't have to wait for the UpdateStatusBarAndStuff method to finish.

Martin
+1  A: 

use `BeginInvoke' instead

Itay
A: 

I would do it a slightly different way:

private Thread workerThread;

void StartButtonClick()
{
    workerThread = new Thread(ReportProgress);
    thread.Start(); 
}

void CancelButtonClick()
{
    // If you use a while(bool), it will repeat the task forever
    // or with no while and just a bool, you'll have to check the value of the bool in each line
    // so simply aborting it (providing you clean up) is accceptable.
    workerThread.Abort();

    // If you don't mind your user waiting:
    // workerThread.Join(1000);
}

void ReportProgress()
{
    if (InvokeRequired)
    {
        Invoke(ReportProgress);
        return;
    }

    UpdateStatusBarAndStuff();
}

The best practice advice is "don't abort". This is based on the fact you don't know at what point the abort call will exit your code - it could be half way through creating a Stream. So you end up with a choice: can you guarantee that at whatever line the code exits, it will be in a reasonable state to do so?

If you can't then you will need to use a Thread.Join().

Even with a Thread.Join, the user may get bored and quit (ALT+F4) the app, and you have exactly the same situation as you had with the Thread.Abort() call.

Chris S