2014-11-05 3 views
2

저는 .NET 4.0에서 C#으로 작업 중이며 Task<T>으로 여러 개의 중첩 된 BackgroundWorker 설정을 바꾸기 시작했습니다.내부에서 연속 체인 취소

은 "둥지"는이 양식이다 :

var secondWorker = new BackgroundWorker(); 
secondWorker.DoWork += (sender, args) => 
{ 
    MoreThings(); 
}; 

var firstWorker = new BackgroundWorker(); 
firstWorker.DoWork += (sender, args) => 
{ 
    args.Result = this.Things(); 
}; 

firstWorker.RunWorkerCompleted += (sender, args) => 
{ 
    var result = (bool)args.Result; 

    // possibly do things on UI 

    if (result) { secondWorker.RunWorkerAsync(); } 
}; 

secondWorker 여기 firstWorker에 대한 콜백의 역할을한다. Task<T>을 사용할 때의 동등 물은 내가 이해할 수 있듯이 ContinueWith(); 그러나 이것은 특정 케이스에서 제어 흐름으로부터 연속을 실제로 실행할 것인지 여부를 결정할 수는 없습니다.

A - - 나의 이해 매우 부정에서 해결이 될 것이다 :

var source = new CancellationTokenSource(); 
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

Task.Factory.StartNew(() => { return this.Things(); }) 
    .ContinueWith(t => 
     { 
      // do things on UI 

      if (!t.Result) { source.Cancel(); } 
     }, CancellationToken.None, TaskContinuationOptions.NotOnFaulted, uiScheduler) 
    .ContinueWith(t => { this.MoreThings(); }, source.Token); 

작품의 이런 종류의, 그러나이 형태의 내가 본 모든 예에서 (계속 내에서 CancellationTokenSource 접근 체인 - 작업은 토큰을 사용하지 않지만 오히려 CancellationToken 메커니즘의 남용처럼 보입니다. 이게 정말 얼마나 나쁜가요? 플로우 내부에서 결정된 정보를 기반으로 연속 체인을 취소하는 "관용적 인"적절한 방법은 무엇입니까?

(이 코드는 의도 한 효과가 있지만 기존 도구를 사용하는 것과 관련하여 작업을 해결하는 잘못된 방법이라고 가정합니다. "솔루션"에 대한 비판은 찾고 있지 않지만 적절한 그게 바로 코드 검토가 아니기 때문입니다.)

+0

예를 들어,'source.Cancel()'은 실제로 두번째'ContinueWith'에서 취소가 요청되었는지 당신이 협력 적으로 확인하지 않기 때문에 실제로 아무것도하지 않을 것입니다. 그게 네가 원하는거야? –

+0

@YuvalItzchakov 취소 된 토큰이 취소로 인해 계속 실행되지 않는 마지막'ContinueWith()'호출로 전달되기 때문에 작동합니다. – TeaDrivenDev

답변

1

계속하면 C#도 async 메소드 기능을 제공합니다. 이 체계에서 코드는 다음과 같이 표시됩니다.

async Task<bool> Things() { ... } 
async Task MoreThings() { ... } 

async Task RunStuff() 
{ 
    if (await Things()) 
    { 
     await MoreThings(); 
    } 
} 

정확한 세부 정보는 구현 세부 사항에 따라 다릅니다. 여기서 중요한 점은 asyncawait을 통해 C#이 연속체를 처리하지 못하도록 모든 지루함을 추상화하는 상태 시스템을 자동으로 생성하여 구성하기 쉽도록하는 것입니다.

편집 : 실제 Things()MoreThings() 방법, 당신은 실제로 async로 변환 할 수 없습니다 것을 나에게 발생, 그래서 당신은 대신이 작업을 수행 할 수 있습니다에 특정 방법을 바꿈됩니다

async Task RunStuff() 
{ 
    if (await Task.Run(() => Things())) 
    { 
     await Task.Run(() => MoreThings()); 
    } 
} 

비동기 작업.

편집 2 : 그것은 내가 여기에 미리 4.5 제한을 간과 나에게 지적 된 다음 작동합니다 : 그런

void RunStuff() 
{ 
    Task.Factory.StartNew(() => Things()).ContinueWith(task => 
    { 
     if (task.Result) 
     { 
      Task.Factory.StartNew(() => MoreThings()); 
     } 
    }); 
} 

뭔가를, 어쨌든.

+0

그건 내가 선호하는 방법이지만 물론 불행히도 우리는 여전히 .NET 4.0/C# 4에 있으므로 아직 사용할 수 없습니다. – TeaDrivenDev

+0

아, 4.0 제한을 알지 못했습니다. 음, 여전히 동일합니다 ... 모든 취소 작업이 필요하지 않습니다. 완료된 작업에서 '결과'를 확인하여 다음 작업을 실행할 것인지 결정하십시오. –

+4

@TeaDrivenDev C# 5.0을 사용하고 있다면 [Microsoft.Bcl.Async 패키지] (http://www.nuget.org/packages/Microsoft.Bcl.Async)를 설치하면 .Net 4.0에서'await'을 사용할 수 있습니다. 컴파일러 (VS2012 +). – svick