6

Động lực

C# 5.0 async/chờ đợi các cấu trúc được tuyệt vời, không may nhưng Microsoft chỉ được hiển thị một ứng cử viên phát hành của cả hai .NET 4.5 và VS 2012, và nó sẽ mất một thời gian cho đến khi các công nghệ này sẽ được áp dụng rộng rãi trong các dự án của chúng tôi.Thực hiện thời gian chờ async sử dụng mans async nghèo/chờ đợi các cấu trúc trong Net 4.0

Trong Stephen Toub Asynchronous methods, C# iterators, and Tasks Tôi đã tìm thấy một thay thế có thể được sử dụng độc đáo trong .NET 4.0. Ngoài ra còn có một tá các triển khai khác làm cho nó có thể sử dụng cách tiếp cận ngay cả trong .NET 2.0 mặc dù họ có vẻ ít lỗi thời và ít tính năng phong phú hơn.

Ví dụ

Vì vậy bây giờ tôi mã NET 4.0 trông giống như (các phần nhận xét thấy làm thế nào nó được thực hiện trong .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)); 
    } 
} 

Trông chút xấu xí mặc dù nó không được công việc

Câu hỏi

Khi sử dụng CancellationTokenSource trong .NET 4.5, có một hàm tạo tham số timepan để kết quả là CancellationTokenSource hủy trong khoảng thời gian được chỉ định.
.Net 4.0 không thể hết thời gian chờ, vì vậy cách thực hiện chính xác điều đó trong .Net 4.0 là gì?

+0

câu hỏi liên quan: http://stackoverflow.com/questions/9110472/using-async-await-on- net-4 – CodesInChaos

+0

Thay đổi "hẹn giờ" thành "hết giờ" trong tiêu đề vì câu hỏi là về thời gian chờ và "hẹn giờ" (được sử dụng để định kỳ với một số lần thực thi) bị gây hiểu lầm và mất phương hướng –

Trả lời

4

Điều này thực sự có liên quan gì đến việc không đồng bộ/chờ đợi không? Có vẻ như bạn chỉ cần một cách để hủy mã thông báo, độc lập với async/await, phải không? Trong trường hợp đó, bạn có thể chỉ cần tạo Bộ hẹn giờ gọi Hủy sau khi hết giờ?

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

EDIT

phản ứng ban đầu của tôi ở trên là ý tưởng cơ bản, nhưng một giải pháp mạnh mẽ hơn là có thể được tìm thấy trong Is CancellationTokenSource.CancelAfter() leaky? (trên thực tế việc thực hiện Net 4.5 của constructor bạn đang tìm kiếm). Dưới đây là một chức năng bạn có thể sử dụng để tạo mã thông báo thời gian chờ dựa trên mã đó.

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

Loại bộ hẹn giờ nào bạn đề xuất sử dụng Dax? – Lu4

+0

'System.Threading.Timer' là những gì tôi đã suy nghĩ, nhưng tôi muốn tưởng tượng bất kỳ trong số họ nên làm việc - Tôi không phải là một chuyên gia về sự khác biệt giữa các loại .Net' Timer 's. –

+0

Nhưng nó sẽ chặn các chủ đề và chúng tôi sẽ bắt đầu mất tất cả những lợi ích của cách tiếp cận không đồng bộ ... :( – Lu4

5

FWIW, bạn có thể sử dụng async/await trong 4.0 dự án, chỉ cần sử dụng the async targeting pack. Hoạt động tuyệt vời cho tôi!

+1

Câu trả lời hữu ích nhất định – Lu4

0

Bạn vẫn có thể sử dụng CancelAfter(), mà là một phương pháp khuyến nông trong Microsoft.Bcl.Async đó rất giống với câu trả lời được chấp nhận ở trên.

Đây là mã refereance souce khi tôi nhấn F12 để xem việc thực hiện 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); 
    } 
Các vấn đề liên quan