Жду в улове - PullRequest
       60

Жду в улове

82 голосов
/ 15 января 2012

У меня есть следующий код:

WebClient wc = new WebClient();
string result;
try
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
}
catch
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
}

По сути, я хочу скачать с URL-адреса, а когда происходит сбой с исключением, я хочу скачать с другого URL-адреса.Оба раза асинхронны конечно.Однако код не компилируется из-за ошибки

CS1985: Не удается дождаться в теле предложения catch

ОК, по какой-то причине он запрещен, но это правильнообразец кода здесь?

РЕДАКТИРОВАТЬ:

Хорошая новость заключается в том, что C # 6.0, скорее всего, позволит ожидать вызовов как в catch, так и в конечном итоге блокирует .

Ответы [ 9 ]

98 голосов
/ 15 января 2012

Обновление: C # 6.0 поддерживает ожидание в перехвате


Старый ответ : Вы можете переписать этот код, чтобы переместить await из блока catch с использованием флага:

WebClient wc = new WebClient();
string result = null;
bool downloadSucceeded;
try
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
  downloadSucceeded = true;
}
catch
{
  downloadSucceeded = false;
}

if (!downloadSucceeded)
  result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
24 голосов
/ 16 апреля 2014

Ожидание в блоке перехвата теперь возможно с предварительного просмотра конечного пользователя Roslyn , как показано здесь (в списке под Await в catch / finally) и будет включено в C # 6.

Приведенный пример:

try … catch { await … } finally { await … }

Обновление: Добавлена ​​более новая ссылка, и она будет в C # 6

9 голосов
/ 27 октября 2012

Это похоже на работу.

        WebClient wc = new WebClient();
        string result;
        Task<string> downloadTask = wc.DownloadStringTaskAsync(new Uri("http://badurl"));
        downloadTask = downloadTask.ContinueWith(
            t => {
                return wc.DownloadStringTaskAsync(new Uri("http://google.com/")).Result;
            }, TaskContinuationOptions.OnlyOnFaulted);
        result = await downloadTask;
5 голосов
/ 04 марта 2015

Попробуйте:

         try
        {
            await AsyncFunction(...);
        }

        catch(Exception ex)
        { 
            Utilities.LogExceptionToFile(ex).Wait();
            //instead of "await Utilities.LogExceptionToFile(ex);"
        }

(см. Окончание Wait())

2 голосов
/ 16 октября 2015

Используйте C # 6.0. смотри Ссылка

public async Task SubmitDataToServer()
{
  try
  {
    // Submit Data
  }
  catch
  {
    await LogExceptionAsync();
  }
  finally
  {
    await CloseConnectionAsync();
  }
}
1 голос
/ 08 ноября 2015

Вы можете использовать лямбда-выражение следующим образом:

  try
    {
        //.....
    }
    catch (Exception ex)
    {
        Action<Exception> lambda;

        lambda = async (x) =>
        {
            // await (...);
        };

        lambda(ex);
    }
1 голос
/ 02 июля 2015

Шаблон, который я использую, чтобы перебросить исключение после ожидания в резервной задаче:

ExceptionDispatchInfo capturedException = null;
try
{
  await SomeWork();
}
catch (Exception e)
{
  capturedException = ExceptionDispatchInfo.Capture(e);
}

if (capturedException != null)
{
  await FallbackWork();
  capturedException.Throw();
}
0 голосов
/ 08 февраля 2015

В аналогичном случае я не смог дождаться в блоке catch.Однако я смог установить флаг и использовать флаг в операторе if (код ниже)

---------------------------------------...

boolean exceptionFlag = false; 

try 
{ 
do your thing 
} 
catch 
{ 
exceptionFlag = true; 
} 

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
}
0 голосов
/ 10 ноября 2014

Вы можете поместить await после блока catch, за которым следует label, и поместить goto в блок try.(Нет, правда! Гото не такие уж плохие!)

...