1

New to async await integration in C# 5. I'm working with some basic Task based methods to explore async await and the TPL. In this example below I'm calling a web service with a timeout of 5 seconds. If the timeout expires it should throw an exception so I can return false from the method. However, the timeout never occurs, or maybe it does but the Task never returns.

public static Task<bool> IsConnectedAsync()
{
    return Task.Run(() =>
    {
        try
        {
            using (WSAppService.AppService svc = new NCSoftware.Common.WSAppService.AppService(GetServiceUrl(WebService.app)){Timeout = 5000})
            {
                return svc.PingB();
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex.Message, ex, "IsConnectedAsync");
        }    
        return false;
    });
}

If you could please help with how to properly handle this so that if the timeout occurs or even better, an exception occurs, the Task does return.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Neal
  • 9,487
  • 15
  • 58
  • 101

1 Answers1

1

In general, you shouldn't use Task.Run if you're wrapping async services. Since this is a service reference, you should be able to expose an async method (returning Task) directly from the service, in which case you could use:

public async static Task<bool> IsConnectedAsync()
{
    try
    {
         using (WSAppService.AppService svc = new NCSoftware.Common.WSAppService.AppService(GetServiceUrl(WebService.app)){Timeout = 5000})
         {
              return await svc.PingBAsync();
         }
     }
     catch (Exception ex)
     {
         Logger.LogException(ex.Message, ex, "IsConnectedAsync");
     }    
     return false;
}

If you must wrap via Task.Run (again, this is not suggested, as it's turning synchronous code into async via the thread pool, which is typically better handled by the user at the top level), you could do:

public async static Task<bool> IsConnectedAsync()
{
    try
    {
       return await Task.Run(() =>
       {
         using (WSAppService.AppService svc = new NCSoftware.Common.WSAppService.AppService(GetServiceUrl(WebService.app)){Timeout = 5000})
         {
              return svc.PingB();
         }
       }
     }
     catch (Exception ex)
     {
         Logger.LogException(ex.Message, ex, "IsConnectedAsync");
         return false;
     }    
}
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Thanks - unfortunately this is an old ASMX .net 2.0 web service so it doesn't have Task based async services available. Only the older Begin... End... type services so I could use a FromAsync I suppose? Not sure if that would be preferred over your second option above? – Neal Aug 09 '13 at 19:39
  • @Neal Yes, I'd wrap it in a FromAsync, then use the first method. – Reed Copsey Aug 09 '13 at 19:43
  • The other problem with your second example is that you can't return false in the exception as you can't convert from false to Task I don't believe. – Neal Aug 09 '13 at 19:48
  • Sorry, and in your first example, shouldn't the caller do the await'ing so it should be return svc.PingBAsync(); without the await? – Neal Aug 09 '13 at 19:49
  • @Neal In the second example, sinc eit's an async method, the compiler will turn the `return false` into a `Task`. In the first example, I didn't have the caller do the awaiting because you have exception handling in place. The await call will make the exception ahndling work. (That's the problem with your original...) – Reed Copsey Aug 09 '13 at 19:50