2013-04-04 2 views
1

У меня есть следующий методИсключения не выброшено в конфигурации Task асинхронном

public async Task<bool> Connect() 
    { 
     lock (_connectingLock) 
     { 
      if (_connecting) 
       throw new IOException("Already connecting"); 
      _connecting = true; 
     } 

     try { 
      await tcpClient.ConnectAsync(...); 
     }   
     catch (SocketException e) 
     { 
      return false; 
     } 
     finally 
     { 
      lock (_connectingLock) 
      { 
       _connecting = false; 
      } 
     } 
    } 

Теперь я хотел бы ожидать последовательные вызовы на Connect() бросить IOException, но этого не происходит!

В чем может быть причина?

ответ

7

Звонки на Connect() не могут напрямую исключать исключения. Асинхронные методы не исключение. Вместо этого они возвратят задачи, которые, когда их ожидают, будут бросать IOException. (. То есть задачи, неисправны)

Если это не то, что вы хотите, вы должны отделить звонки:

public Task<bool> Connect() 
{ 
    // Eager validation of state... 
    lock (_connectingLock) 
    { 
     if (_connecting) 
      throw new IOException("Already connecting"); 
     _connecting = true; 
    } 
    return ConnectImpl(); 
} 

private async Task<bool> ConnectImpl() 
{ 
    try { 
     await tcpClient.ConnectAsync(...); 
    }   
    catch (SocketException e) 
    { 
     return false; 
    } 
    finally 
    { 
     lock (_connectingLock) 
     { 
      _connecting = false; 
     } 
    } 
} 

Это не ясно, будет ли уместно в данном случае, хотя. В целом хорошо бросать вещи, такие как ArgumentException с нетерпением, но если ошибка не представляет собой ошибку в самом вызывающем коде, я думаю, что возвращать ошибочную задачу, это нормально.

+0

Вот! NCrunch стал зеленым. Ура! – kasperhj

+0

Этот случай также достаточно прост, что вы можете реализовать его с помощью 'ContinueWith', а не' await', так что исключения должны быть явно заключены в результирующую задачу, а не в неявно. – Servy

Смежные вопросы