1
votes

I have a simple and very literal WPF wherein when I click start, it will start doing work and if I click stop, it will stop. Code for starting the worker/background thread is:

--- variables ---
Thread[] thd;
bflag = false;

--- Start background worker when Start button is clicked ---
private void btnStart_Click(object sender, RoutedEventArgs e)
{
   Thread startFileCopy = new Thread(() => startFC());
   startFileCopy.Start();  
}

--- StartFC code ---
private void startFC()
{
   bflag = true;
   thd = new Thread[3];
   for(int i=0; i<3; i++)
   {
      thd[i] = new Thread(copynow);
      thd[i].Start();
   }
}

--- copynow code ---
private void copynow()
{
   while(bflag)
   {
      if (filecount == 0)
        bflag = false;
      else
      {
         // --- copy file ---
         Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
               new Action(() => copyFile(<filename to be copied>)));
         // --- update progressbar ---
         Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
               new Action(() => updateProgressbar(++1)));
      }
   }
}

Now to stop this, on my cancel button, I dispatched another thread with Send as priority to set bflag to false. However, based on the responses on my UI, the progressbar is still updating and the file copy still continues. Code for my stop button:

--- Stop when stop button is clicked ---
private void btnStop_Click(object sender, RoutedEventArgs e)
{
   Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Send, 
              new Action(() => stopThreads()));
}

--- stopThreads code ---
private void stopThreads()
{
   bflag = false;
   if (thd != null)
     for (int i = 0; i < THREAD_COUNT; i++)
       if (thd[i].IsAlive)
          thd[i].Join(3000);
}

What am I doing wrong? Thanks in advance!

1

1 Answers

2
votes

The problem with your thread method is that it repeatedly starts the asynchronous execution of the copyFile method by BeginInvoke:

// --- copy file ---
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
    new Action(() => copyFile(<filename to be copied>)));

This creates a lot of operations that are queued for exection on the Dispatcher queue. Even when your thread is stopped there are still lots of these queued operation left, which makes you think the thread is still running.

You need to change your code in a way that it actually performs the copy operation in the thread method:

private void copynow()
{
    while (bflag && filecount > 0)
    {
        copyFile(<filename to be copied>);

        // update progressbar by synchronous Invoke instead of BeginInvoke
        Application.Current.Dispatcher.Invoke(
            new Action(() => updateProgressbar(++1)));
    }
}