C# 5.0 async/await constructs are awesome, unfortunately yet Microsoft only shown a release candidate of both .NET 4.5 and VS 2012, and it will take some time until these technologies will get widely adopted in our projects.
In Stephen Toub's Asynchronous methods, C# iterators, and Tasks I've found a replacement that can be nicely used in .NET 4.0. There are also a dozen of other implementations that make it possible using the approach even in .NET 2.0 though they seem little outdated and less feature-rich.
So now my .NET 4.0 code looks like (the commented sections show how it is done in .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));
}
}
Looks little ugly though it does the job
When using CancellationTokenSource in .NET 4.5 there is a constructor that takes timespan as a timeout parameter, so that resulting CancellationTokenSource
cancels within specified period of time.
.Net 4.0 is not able to timeout, so what is the correct way of doing that in .Net 4.0?
FWIW, you can use async/await in 4.0 projects, just use the async targeting pack. Works Great For Me!
Does this really have anything to do with async/await? Looks like you're just needing a way to cancel the token, independently of async/await, right? In that case, could you simply create a Timer that calls Cancel after the timeout?
new Timer(state => cts.Cancel(), null, BootstrapResponseTimeout, Timeout.Infinite);
EDIT
My initial response above is the basic idea, but a more robust solution is can be found in Is CancellationTokenSource.CancelAfter() leaky? (actually the .Net 4.5 implementation of the constructor you're seeking). Here's a function you can use to create timeout tokens based on that code.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With