2013-05-17 5 views
2
 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"); 
     } 

이 줄을 모두 주석 처리하고 예외가 주 스레드에서 catch되면 이해할 수 없는데이 줄 예외를 자식 스레드에서 throw합니다. 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); 

I 프로세스 예외를했지만, 그렇지 취소 설정하는 작업의 상태에 이르게. 지금은 작업이 처리하기 위해 예외를 잡을 수 없기 때문이라고 생각합니다. 올바른 방법은 무엇입니까?

찾았습니다 http://msdn.microsoft.com/en-us/library/ee191553.aspx이 예제와 같은 문제가 있습니다! 실행 중에 'c'를 누르면 externalToken.ThrowIfCancellationRequested()를 호출하여 다시 시작하려고 할 때 처리되지 않은 예외가 발생합니다. 나는 혼란 스럽다. x64 Win 7, 4.5를 사용하고 있습니다. NET Framework

답변

2

줄을 주석 처리 할 때 우리의 작업은 시작되기 전에 취소됩니다. 따라서 예외가 발생합니다. 수면을 추가하면 거의 시작될 것이므로 ThrowIfCancellationRequested

+0

좋아,하지만 그 행동이 동일해야한다고 생각. 왜 그것이 작업 시작 여부를 의미합니까? Here docs info : 작업 인스턴스가 사용자 코드에 의해 Throw 된 OperationCanceledException을 관찰 할 때 예외 토큰을 관련 토큰과 비교합니다 (다음 주석을 보면 길이가 너무 깁니다.) –

+0

(해당 작업을 생성 한 API에 전달 된 것임) 태스크). 이들이 같고 토큰의 IsCancellationRequested 속성이 true를 반환하면 작업은 이것을 확인 응답으로 해석하고 취소 상태로 전환합니다. Wait 또는 WaitAll 메서드를 사용하여 작업을 기다리지 않으면 해당 작업의 상태가 Canceled로 설정됩니다 .--- 내가 알고 있듯이 wait 메서드가 없으면 예외가 발생하지 않아야합니다. Wait 메서드를 사용하여 주 스레드에서 throw해야합니다. 나는 http://msdn.microsoft.com/en-us/library/dd997396(v=vs.100).aspx –

+0

에서 가져 갔다. 나는 생각을 이해하지 못했다.따라서 몇 가지 예제를 검토하고 태스크의 스레드가 시작되지 않은 경우 호출 스레드에서 예외를 catch해야하지만 이미 시작된 경우 태스크의 스레드에서 예외를 호출하지 않는 것이 좋습니다. 내가 맞습니까? –

0

이 항목의 내용은 documentation입니다.

Task.Wait 방법

태스크 예외가 태스크의 실행 중에 슬로우 - 또는 취소

AggregateException. 작업이 취소 된 경우 AggregateException에는 InnerExceptions 컬렉션에 OperationCanceledException이 포함되어 있습니다.

본질적으로 당신이 이기면 task.Wait으로 만들면 경쟁 조건이됩니다.

+0

으로 전화를 걸어 취소 할 수 있습니다. 죄송 합니다만 답변을 이해하지 못했습니다. 무슨 소리 야? 취소 작업이 호출 될 때 작업이 여전히 실행 중입니다 (스레드 수면,하지만 상관 없습니다, 나는 생각합니다). 나는 메인 스레드에서 1sc 지연으로 슬립에 대해 이야기하고있다. 예외가 잡힌 곳에서 어떻게 영향을 미칠 수 있습니까? 우리는 task.Wait()을 삭제할 수 있으며 예외는 여전히 태스크의 스레드에서 catch되지만 이해할 수는 있습니다. Wait 메소드를 호출하지 않으면 태스크의 내부 핸들러가이를 catch하고 Canseled 상태를 설정하기 때문에 catch하지 않아야합니다. 제발, 나를 위해 명확하게 :) –