How to reset the CancellationTokenSource and debug the multithread with VS2010?

q0987 picture q0987 · May 29, 2011 · Viewed 18.7k times · Source

I have used CancellationTokenSource to provide a function so that the user can cancel the lengthy action. However, after the user applies the first cancellation, the later further action doesn't work anymore. My guess is that the status of CancellationTokenSource has been set to Cancel and I want to know how to reset it back.

  • Question 1: How to reset the CancellationTokenSource after the first time usage?

  • Question 2: How to debug the multithread in VS2010? If I run the application in debug mode, I can see the following exception for the statement

    this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
    

InvalidOperaationException was unhandled by user code Cross-thread operation not valid: Control 'MainForm' accessed from a thread other than the thread it was created on.

Thank you.

private CancellationTokenSource cancelToken = new CancellationTokenSource();

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew( () =>
    {
        ProcessFilesThree();
    });
}

private void ProcessFilesThree()
{
    ParallelOptions parOpts = new ParallelOptions();
    parOpts.CancellationToken = cancelToken.Token;
    parOpts.MaxDegreeOfParallelism = System.Environment.ProcessorCount;

    string[] files = Directory.GetFiles(@"C:\temp\In", "*.jpg", SearchOption.AllDirectories);
    string newDir = @"C:\temp\Out\";
    Directory.CreateDirectory(newDir);

    try
    {
        Parallel.ForEach(files, parOpts, (currentFile) =>
        {
            parOpts.CancellationToken.ThrowIfCancellationRequested();

            string filename = Path.GetFileName(currentFile);

            using (Bitmap bitmap = new Bitmap(currentFile))
            {
                bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                bitmap.Save(Path.Combine(newDir, filename));
                this.Text =  tring.Format("Processing {0} on thread {1}",  filename, Thread.CurrentThread.ManagedThreadId);
            }
        });

        this.Text = "All done!";
    }
    catch (OperationCanceledException ex)
    {
        this.Text = ex.Message;                             
    }
}

private void button2_Click(object sender, EventArgs e)
{
    cancelToken.Cancel();
}

Answer

CodesInChaos picture CodesInChaos · May 29, 2011

Question 1> How to reset the CancellationTokenSource after the first time usage?

If you cancel it, then it's cancelled and can't be restored. You need a new CancellationTokenSource. A CancellationTokenSource isn't some kind of factory. It's just the owner of a single token. IMO it should have been called CancellationTokenOwner.

Question 2> How to debug the multithread in VS2010? If I run the application in debug mode, I can see the following exception for the statement

That has nothing to do with debugging. You can't access a gui control from another thread. You need to use Invoke for that. I guess you see the problem only in debug mode because some checks are disabled in release mode. But the bug is still there.

Parallel.ForEach(files, parOpts, (currentFile) =>
{
  ...  
  this.Text =  ...;// <- this assignment is illegal
  ...
});