views:

51

answers:

1

I made a program to test Parallel programming in C# 4.0. However, there is a problem and I can't figure out why.

I write a method

    private void compute(int startValue, int endValue, ConcurrentBag<Pair> theList)
    {
        try
        {
            Task computation = Task.Factory.StartNew(() => { findFriendlyNumbers(startValue, endValue, theList, tokenSource.Token); }, tokenSource.Token);
            Task.WaitAll(computation);
            StringBuilder builder = new StringBuilder();
            foreach (Pair p in theList)
            {
                builder.AppendLine(p.ToString());
            }

            this.textBlockResult.Dispatcher.Invoke(new Action(() =>
            {
                this.textBlockResult.Text = builder.ToString();
                this.progressBar1.Visibility = System.Windows.Visibility.Hidden;
            }));
        }
        catch (AggregateException aEx)
        {
            MessageBox.Show("Entering");  //For debug, but never runs
            aEx.Handle(handleCancelling);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

Which is run on a separate thread (other than the UI thread).

And the function (simplified)

        private void findFriendlyNumbers(int start, int end, ConcurrentBag<Pair> list, CancellationToken token)
    {
        //some initialization and computation

        for (int i = start; i <= end; i++)
        {
            //check whether it's cancelled
            token.ThrowIfCancellationRequested();

            //some computation
        }
    }

The problem is, when the tokenSource is canceled, there will be an error "OperationCanceledException is not handled by user code", as if the catch block doesn't exist. I am not sure why, because my code is similar to that in textbook and also in MSDN.

Thank you.

EDIT: I actually wrote a similar program less than a month ago, and everything was fine then. Today I tried to run it again, the same problem happened. I installed Microsoft Visual Web Developer 2010 Express after I finished the program, and I am not sure whether this is the reason. I don't get it, the same code, different results.

EDIT: I thought about this problem and found where is wrong. In the past, I used to use "run without debugging" while I use debug now. Running without debugging solves the problem. And I will appreciate it if someone tells me why debug is different from "run without debug".

A: 

You're passing the cancellation token in to the TaskFactory.StartNew method. This makes the Task treat it specially: as an indication of cancellation instead of an error.

If you don't pass the token as a parameter to TaskFactory.StartNew, then it will be treated as an error and caught. If you do keep it as a parameter, then you need to check for cancellation using Task.IsCanceled instead of an exception.

Side note: it's best not to use Invoke to synchronize to the UI thread. I have an example of Task objects properly doing UI progress updates on my blog.

Stephen Cleary
Thanks a lot, but it's not the real problem. See http://msdn.microsoft.com/en-us/library/dd997396.aspx, it's similar to mine.I know I can simply check the IsCancellationRequested, but if I don't use exception to stop the task, the status of task will remain RanToComplete.
LLS
Read my answer again. `Task.IsCanceled`, not `CancellationToken.IsCancellationRequested`.
Stephen Cleary
@Stephen Cleary : Sorry. I tried to remove the token argument, but the result is the same. And I'm not sure how to check Task.IsCanceled if there is no way to cancel the task first.
LLS
@Stephen Cleary : I found a strange problem. I tried to run an example in the textbook that I worked out earlier. I found the cancellation has the same problem. But I finished the example and tested it, it was functioning properly at that time. The only thing I can think of is that I installed Microsoft Visual Web Developer 2010 Express after the test.
LLS
@LLS: Make absolutely sure that you're passing the *same* cancellation token to the task function and `StartNew`.
Stephen Cleary