Neal
Neal

Reputation: 9629

Exception not caught in Task.Run wrapped method

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.

Upvotes: 1

Views: 1927

Answers (1)

Reed Copsey
Reed Copsey

Reputation: 564333

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;
     }    
}

Upvotes: 1

Related Questions