6

yapılar müthiş maalesef henüz Microsoft sadece her iki .NET 4.5 ve VS 2012 ve bunun bir sürüm adayı gösterilir bekliyor verisimi

C# 5.0 zaman uyumsuz/Motivasyon Bu teknolojiler projelerimizde yaygın olarak benimsenene kadar biraz zaman alacaktır./.NET yapıları bekliyor 4.0

Stephen Toub'nin Asynchronous methods, C# iterators, and Tasks numaralı sürümünde .NET 4.0'da güzel bir şekilde kullanılabilen bir değiştirme buldum. Ayrıca, biraz güncelliğini yitirmiş ve daha az özellik bakımından zengin olsa da, .NET 2.0'da bile bu yaklaşımı kullanarak bunu mümkün kılan bir düzine başka uygulama vardır.

Örnek

Yani şimdi benim .NET 4.0 kod benziyor (yorumladı bölümler de .NET 4.5 nasıl yapılır göster): iş yapar gerçi

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

küçük çirkin görünüyor

soru

.NET 4.5 CancellationTokenSource oçıkan böylece, bir zaman aşımı parametre olarak zaman aralığı alan bir kurucu yoktur kullanılarakbelirli bir süre içinde iptal eder.
.Net 4.0, zaman aşımı yapamıyor, bu yüzden .Net 4.0'da bunu yapmanın doğru yolu nedir?

+0

İlgili soru: http://stackoverflow.com/questions/9110472/using-async-await-on- Ben CancelAfter() uygulanmasını görmek için F12 tuşuna bastığınızda

Bu

refereance sos kodu olduğunu net-4 – CodesInChaos

+0

Sorunun zaman aşımı ve "zamanlayıcı" (zaman aşımıyla bazı dönem yürütmeleri için yinelenen için kullanılan) hakkında "zaman aşımı" için başlıkta "zaman aşımı" olarak değiştirildi. Yanıltıcı ve şaşırtmalı –

cevap

4

Bu gerçekten async/await ile ilgili bir şey var mı? Görünüşe göre, belirteci, beklemeden/beklemeden bağımsız olarak iptal etmenin bir yoluna ihtiyacınız var değil mi? Bu durumda, zaman aşımından sonra İptal'i çağıran bir Zamanlayıcı oluşturabilirsiniz.

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

DÜZENLEME

Benim ilk tepki yukarıdaki temel fikir, ama daha sağlam bir çözüm Is CancellationTokenSource.CancelAfter() leaky? içinde (aradığınız yapıcı aslında .Net 4.5 uygulaması) bulunabilir edilir. İşte, bu koda dayalı olarak zaman aşımı simgeleri oluşturmak için kullanabileceğiniz bir işlev.

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

Ne tür bir zamanlayıcı önerirsiniz? Dax kullan? – Lu4

+0

'System.Threading.Timer' düşündüğüm şeydir, ama bunların hepsinin çalışması gerektiğini düşünürdüm - .Net' Timer'ler arasındaki farklar konusunda uzman değilim. –

+0

Ama iş parçacığı engeller ve biz asenkronize yaklaşımın tüm faydalarını kaybetmeye başlayacağız ... :( – Lu4

5

FWIW, 4.0 projelerinde async/await kullanabilirsiniz, sadece the async targeting pack kullanın. Benim için harika çalışıyor!

+1

Kesinlikle yardımcı yanıt – Lu4

0

Hala yukarıda kabul edilen yanıt çok benzer Microsoft.Bcl.Async bir uzantısı yöntemidir CancelAfter() kullanabilirsiniz.

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