2012-01-15 34 views
73

Tôi có đoạn mã sau:Chờ trong khối catch

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

Về cơ bản tôi muốn tải về từ một URL và khi nó không thành công với một ngoại lệ Tôi muốn tải về từ URL khác. Cả hai thời gian không đồng bộ của khóa học. Tuy nhiên mã không biên dịch, vì

lỗi CS1985: Không thể chờ đợi trong cơ thể của một mệnh đề catch

OK, nó bị cấm vì lý do gì nhưng mã mẫu đúng là những gì ở đây?

EDIT:

Các tin tốt là C# 6.0 will likely allow await calls both in catch and finally blocks.

Trả lời

87

Cập nhật:C# 6.0 supports await in catch


Old trả lời: Bạn có thể viết lại mã để di chuyển await từ khối catch sử dụng một lá cờ:

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")); 
+7

Cảm ơn svick, đó là khá rõ ràng, bất cứ điều gì tốt hơn, kết nối hơn để async? –

+0

Tôi không nghĩ rằng bất cứ điều gì như thế tồn tại. – svick

+3

Trong trường hợp của bạn, bạn cũng có thể sử dụng nhiệm vụ tiếp tục. Nhưng mã trong câu trả lời 'svick' là sạch hơn so với mã sử dụng sự tiếp tục. –

9

Điều này dường như làm việc.

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

Đang chờ trong một khối catch bây giờ có thể là của người dùng cuối Xem trước Roslyn as shown here (Listed under Await in catch/finally) và sẽ được đưa vào C# 6.

Ví dụ liệt kê là

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

Cập nhật: Đã thêm liên kết mới hơn và liên kết sẽ ở trong C# 6

0

Bạn có thể đặt await sau khối catch theo sau là label và đặt goto trong khối thử. (Không, thực sự! Goto không phải là xấu!)

0

Trong trường hợp tương tự, tôi không thể chờ trong một khối bắt. Tuy nhiên, tôi đã có thể đặt cờ và sử dụng cờ trong câu lệnh if (Mã bên dưới)

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

boolean exceptionFlag = false; 

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

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
} 
4

này cung cấp cho một thử:

  try 
     { 
      await AsyncFunction(...); 
     } 

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

(Xem Wait() kết thúc)

1

các mô hình tôi sử dụng để tính lại ngoại lệ sau khi chờ đợi một tác vụ dự phòng:

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

if (capturedException != null) 
{ 
    await FallbackWork(); 
    capturedException.Throw(); 
} 
2

Sử dụng C# 6.0.thấy điều này Link

public async Task SubmitDataToServer() 
{ 
    try 
    { 
    // Submit Data 
    } 
    catch 
    { 
    await LogExceptionAsync(); 
    } 
    finally 
    { 
    await CloseConnectionAsync(); 
    } 
} 
1

Bạn có thể sử dụng một biểu thức lambda như sau:

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

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

     lambda(ex); 
    } 
+0

Điều này làm cho lambda 'async void', mà không nên được sử dụng, trừ khi bạn phải. – svick

Các vấn đề liên quan