Robert Oschler
Robert Oschler

Reputation: 14385

Adding robust time-outs to a C# asynchronous callback scenario?

I came across this C# code sample on MSDN that shows how to use a delegate to wrap a callback method for an asynchronous DNS lookup operation:

http://msdn.microsoft.com/en-us/library/ms228972.aspx

As you can see from the code, a counter is incremented by the initiating method for each request and decremented once each time the callback method is executed. The initiating method sits in a loop until the counter reaches zero, keeping the UI updated as it waits. What I don't see in the sample is a robust method for timing out the initiating method if the process takes too long. My questions are:

Upvotes: 0

Views: 233

Answers (1)

Shahar Prish
Shahar Prish

Reputation: 4847

The Dns class specifically does not have a facility for cancelling requests. Some APIs do (generated WCF proxies) others don't (Dns and many others).

As for your questions (answering in the context of Timeout):

  1. There are multiple ways of making the uber-request (the async request that wraps the multiple DNS requests) time out. One can simply check for time passed where the code calls UpdateUserInterface. That would be the simplest way in the context of this sample (though will probably fall short for most real-world scenarios, unless you are willing to take up a thread to do it). As for clean-up - if you mean memory clean up after the operation completes, that will happen (unless there's a library bug). If you instead mean clean up to conserve resources, truth is most people don't bother in most cases. The cost and added complexity (coupled with the fact that it's a "less travelled path" meaning less testing) means that calls that should be aborted are often just left alone and complete on their own sweet time. One just needs to make sure the continue code does not do anything bad.

  2. Doing a non-blocking timeout with Tasks (await/async) is actually very compelling, if you have access to it.. All you need to do is the following (pseudo code):

    async Task> GetAddresses(IEnumerable hosts, int timeoutms) { List> tasks = new List>(); foreach (var host in hosts) { tasks.Add(GetEntryAsync(host); } var wait = Task.Delay(timeoutms); // create a task that will fire when time passes. var any = await Task.WhenAny( wait, Task.WhenAll(tasks)); // Wait for EITHER timeout or ALL the dns reqs. if (any == wait) { throw new MyTimeoutException(); }

    return tasks.Select(t => t.Result).ToArray(); // Should also check for exceptions here. }

  3. No tips really.. A good portion of async operations are not even cancellable and, at least in my opionion, are not worth re-writing just to get cancellation semantics.

Upvotes: 1

Related Questions