6

구조 끝내 불행하게도 아직 Microsoft는 모두 .NET 4.5 VS 2012, 그리고 그것의 릴리스 후보를 나타내 기다리고 있습니다

C# 5.0 비동기/동기 부여 이 기술들이 우리 프로젝트에 널리 채택 될 때까지 시간이 걸릴 것입니다.은/닷넷에서 구조를 기다리고 4.0

스티븐 투브 (Stephen Toub)의 Asynchronous methods, C# iterators, and Tasks에서 저는 .NET 4.0에서 잘 사용될 수있는 대체물을 발견했습니다. .NET 2.0에서도이 접근법을 사용할 수있게 해주는 12 가지 구현이 있습니다.하지만 구식이 아닌 기능이 풍부하지는 않습니다.

그래서 지금 내 .NET 4.0 코드는 같습니다 (주석 섹션이 .NET 4.5에서 수행되는 방법을 보여줍니다) :이 작업을 수행하지만

//private async Task ProcessMessageAsync() 
private IEnumerable<Task> ProcessMessageAsync() 
{ 
    //var udpReceiveResult = await udpClient.ReceiveAsync(); 

    var task = Task<UdpAsyncReceiveResult> 
       .Factory 
       .FromAsync(udpClient.BeginReceive, udpClient.EndReceive, null); 

    yield return task; 

    var udpReceiveResult = task.Result; 

    //... blah blah blah 

    if (message is BootstrapRequest) 
    { 
     var typedMessage = ((BootstrapRequest)(message)); 

     // !!! .NET 4.0 has no overload for CancellationTokenSource that 
     // !!! takes timeout parameter :(
     var cts 
      = new CancellationTokenSource(BootstrapResponseTimeout); // Error here 

     //... blah blah blah 

     // Say(messageIPEndPoint, responseMessage, cts.Token); 

     Task.Factory.Iterate(Say(messageIPEndPoint, responseMessage, cts.Token)); 
    } 
} 

조금 못생긴 보이는

질문

.NET 4.5 CancellationTokenSource을 그를 생성하며,이 타임 아웃 시간 범위를 파라미터로하는 생성자가 존재하여지정된 기간 내에 취소합니다. .Net 4.0에서 시간 제한을 설정할 수 없으므로 .Net 4.0에서 올바른 방법은 무엇입니까?

+0

관련 질문 : http://stackoverflow.com/questions/9110472/using-async-await-on- 내가 CancelAfter()의 구현을보기 위해 F12 키를 누르면

은 refereance 소스도 코드 net-4 – CodesInChaos

+0

제목이 시간 제한에 관한 것이고 "타이머"(일부 기간 실행과 함께 반복적으로 사용됨)가 오도 된 것으로 생각되어 제목에 "timer"가 "timeout"으로 변경되었습니다. –

답변

4

async/await와 관련이 있습니까? async/await와 독립적으로 토큰 취소 방법이 필요한 것 같습니다. 이 경우 시간 초과 후 Cancel을 호출하는 Timer를 간단하게 만들 수 있습니까?

new Timer(state => cts.Cancel(), null, BootstrapResponseTimeout, Timeout.Infinite); 

편집

내 초기 반응은 위의 기본 개념이지만,보다 강력한 솔루션은 Is CancellationTokenSource.CancelAfter() leaky?에 (당신이 찾고있는 생성자 실제로 닷넷 4.5 구현을) 찾을 수있다. 다음은 해당 코드를 기반으로하는 시간 초과 토큰을 만드는 데 사용할 수있는 함수입니다.

public static CancellationTokenSource CreateTimeoutToken(int dueTime) { 
    if (dueTime < -1) { 
     throw new ArgumentOutOfRangeException("dueTime"); 
    } 
    var source = new CancellationTokenSource(); 
    var timer = new Timer(self => { 
     ((Timer)self).Dispose(); 
     try { 
      source.Cancel(); 
     } catch (ObjectDisposedException) {} 
    }); 
    timer.Change(dueTime, -1); 
    return source; 
} 
+0

어떤 타이머를 제안합니까? Dax 사용 하시겠습니까? – Lu4

+0

'System.Threading.Timer'는 제가 생각한 것입니다. 그러나 그들 중 누구라도 일해야한다고 생각합니다. 저는 다양한 종류의 .Net'Timer' 사이의 차이점에 대한 전문가가 아닙니다. –

+0

하지만 스레드를 차단할 것이고 비동기 접근법의 모든 이점을 잃어 버리게 될 것입니다 : ( – Lu4

5

FWIW, 4.0 프로젝트에서 async/await을 사용할 수 있습니다. the async targeting pack 만 사용하십시오. 나를 위해 위대한 작품!

+1

확실히 도움이되는 대답 – Lu4

0

당신은 여전히 ​​위의 허용 대답과 매우 유사 Microsoft.Bcl.Async의 확장 방법은 CancelAfter()를 사용할 수 있습니다.

/// <summary>Cancels the <see cref="T:System.Threading.CancellationTokenSource" /> after the specified duration.</summary> 
    /// <param name="source">The CancellationTokenSource.</param> 
    /// <param name="dueTime">The due time in milliseconds for the source to be canceled.</param> 
    public static void CancelAfter(this CancellationTokenSource source, int dueTime) 
    { 
    if (source == null) 
     throw new NullReferenceException(); 
    if (dueTime < -1) 
     throw new ArgumentOutOfRangeException("dueTime"); 
    Contract.EndContractBlock(); 
    Timer timer = (Timer) null; 
    timer = new Timer((TimerCallback) (state => 
    { 
     timer.Dispose(); 
     TimerManager.Remove(timer); 
     try 
     { 
     source.Cancel(); 
     } 
     catch (ObjectDisposedException ex) 
     { 
     } 
    }), (object) null, -1, -1); 
    TimerManager.Add(timer); 
    timer.Change(dueTime, -1); 
    }