Sunday, March 27, 2011

How bad is this pattern?

I've been using this pattern when I need to control how long various async operations take. I don't mean specifically for WebRequest (I know you can set the timeout property), I just used this as an example for the pattern.

        var request = WebRequest.Create(someUri);

        WebResponse response = null;
        request.BeginGetResponse(result =>
            {
                var asyncRequest = (WebRequest)result.AsyncState;
                response = asyncRequest.EndGetResponse(result);
            }, request);

        DateTime timeout = DateTime.Now.AddSeconds(10);
        while (response == null && DateTime.Now <= timeout)
        {
            Thread.Sleep(0);
        }
        if (response == null) throw new Exception("Timeout!");

Anywhere I read about Thread.Sleep(), I heard it's a baaaad thing to do, but I don't really think this use case abuses it.

I know it is possible that it could be a little bit more than exactly 10 seconds, but that isn't important to me.

So, is this truly a bad way to accomplish what I'm accomplishing, and if so, what is a better way to do it?

EDIT: Perhaps I should clarify what I"m trying to accomplish.

The purpose is to control the maximum amount of time spent waiting on a call. I'm aware that this defeats the purpose of an async call, but the intention was never to be asynchronous, I'm just using it as a means to control when I exit a call.

From stackoverflow
  • The WaitHandles wait methods supports time out, use that. Something like:

      var asyncResult = request.BeginGetResponse(...
      asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(10))
    
    Daniel Schaffer : Aha! It seems so obvious!
  • For completeness: to avoid blocking the current thread, use System.Threading.Timer.

    Patrik Hägne : It seems to me from the code example that the desired behavior is to block the current thread.
    Ed Swangren : Then why make it asynchronous?
    Simon Buchan : @Patrik: Yes, but google will probably find this in response "timeout async" or somesuch. @Ed: so you can timeout.
  • Code looks perfectly fine too me. It's just a way to support timeout property on sync call if there's none in the api. Although I should say you'd better replace this waiting loop with some kind of WaitHandle class, it'll use less resources and I'm sure will look better. Sorry, can't provide the solution since I don't know C# and it's API that well.

0 comments:

Post a Comment