多线程 - 不了解情况

时间:2013-05-17 04:59:44

标签: c# .net multithreading

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Factory.StartNew(() => { 
                     Thread.Sleep(4000);
                     Console.WriteLine("Done");
                     ct.ThrowIfCancellationRequested(); 
                   }, ct);

        Thread.Sleep(1000); Look here! <--- 
        tokenSource2.Cancel();

        try
        {
            Console.WriteLine("Wait");
            task.Wait();
        }
        catch (Exception e)
        {
            Console.WriteLine("Task was canceled");
        }

我无法理解为什么如果我评论这一行一切正常并且在主线程中捕获了异常,但是如果我离开这一行,则在ct.ThrowIfCancellationRequested()行中的子线程中抛出异常;在这两种情况下,我们都有一个取消令牌实例。我是多线程的新手,所以我绝对错过了一些东西。

我尝试了下一个代码

    static void Main(string[] args)
    {
        Thread.CurrentThread.Name = "Main";

        Console.WriteLine("Name of the current thread is " + Thread.CurrentThread.Name);

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;
        var task = Task.Factory.StartNew(() => 
        { 
            Thread.Sleep(4000); 
            Console.WriteLine("Done");

            try
            {
                ct.ThrowIfCancellationRequested(); // If I remove the try/catch here will be unhandled exception
            }
            catch (OperationCanceledException exp)
            {
                Console.WriteLine("Task was started then canceled");   
            }

        }, ct);//ontinueWith(OnProcessImageEnded);

        Thread.Sleep(1000);
        tokenSource2.Cancel();

        try
        {
            Console.WriteLine("Wait");
            task.Wait();
        }
        catch (Exception e)
        {
            Console.WriteLine("Task was canceled");
        }

        Console.WriteLine("Task was finished");

        Console.WriteLine(task.Status);

我现在在任务的线程中处理异常,但它导致任务的状态不被设置为已取消。我认为这是因为现在任务无法捕获异常来处理它。什么是正确的方法?

我发现这个例子http://msdn.microsoft.com/en-us/library/ee191553.aspx并且它有同样的问题!如果我们在执行期间按下'c',当我们尝试通过调用externalToken.ThrowIfCancellationRequested()来重新抛出时,它将抛出未处理的异常; ......我很困惑。我正在使用x64 Win 7,4.5 .net框架

2 个答案:

答案 0 :(得分:2)

当您对该行发表评论时,我们的任务即使在启动之前也可能被取消。因此你得到了例外。当您添加睡眠时 - 大多数情况下它会被启动,因此在您调用ThrowIfCancellationRequested

的任务中,取消就会发生

答案 1 :(得分:0)

我会按照documentation推荐这个。

  

Task.Wait方法

     

AggregateException

     

任务被取消 - 或 - 在此期间抛出异常   执行任务。如果任务被取消,那么   AggregateException包含一个OperationCanceledException   InnerExceptions集合。

基本上这是一种竞争条件,如果你及时获得task.Wait,你就赢了。