2010-08-23 96 views
0

我制作了一个程序来测试C#4.0中的并行编程。但是,有一个问题,我不明白为什么。为什么调试与不调试(取消任务)不同?

我写一个方法

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); 
     } 
    } 

其是在单独的线程(除UI线程以外)上运行。

和函数(简化的)

 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 
     } 
    } 

的问题是,当tokenSource被取消时,会出现一个错误“OperationCanceledException不是由用户代码来处理”,如果catch块不一样存在。我不确定为什么,因为我的代码与教科书和MSDN中的类似。

谢谢。

编辑: 我实际上写了一个不到一个月前的类似程序,一切都很好。今天我试图再次运行,发生同样的问题。我在完成该程序后安装了Microsoft Visual Web Developer 2010 Express,但我不确定这是否是原因。我不明白,相同的代码,不同的结果。

编辑: 我想到了这个问题,发现哪里错了。在过去,我曾经使用“无需调试运行”,而现在我使用调试。无调试运行可解决问题。如果有人告诉我为什么调试与“无调试运行”不同,我将不胜感激。

回答

1

您正在将取消令牌传递给TaskFactory.StartNew方法。这使得Task专门处理:作为取消而不是错误的指示。

如果您没有将令牌作为参数传递给TaskFactory.StartNew,那么它将被视为错误并被捕获。如果确实将它作为参数保存,则需要使用Task.IsCanceled来检查取消,而不是例外。

备注:最好不要使用Invoke来同步到UI线程。 I have an example of Task objects properly doing UI progress updates on my blog.

+0

非常感谢,但这不是真正的问题。请参阅http://msdn.microsoft.com/en-us/library/dd997396.aspx,它与我的类似。 我知道我可以简单地检查IsCancellationRequested,但如果我不使用异常来停止任务,任务的状态将保持RanToComplete。 – LLS 2010-08-23 03:22:54

+0

再次阅读我的答案。 'Task.IsCanceled',而不是'CancellationToken.IsCancellationRequested'。 – 2010-08-23 03:30:48

+0

对不起。我试图删除令牌参数,但结果是一样的。而且我不确定如何检查Task.IsCanceled是否无法先取消任务。 – LLS 2010-08-23 03:39:42