Yakalama bloğunda bekleyin


85

Takip koduna sahibim:

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

Temel olarak bir URL'den indirmek istiyorum ve bir istisna ile başarısız olduğunda başka bir URL'den indirmek istiyorum. Elbette her ikisi de asenkron. Ancak kod derlenmez, çünkü

CS1985 hatası: Bir catch cümlesinin gövdesinde beklenemez

Tamam, her ne sebeple olursa olsun yasak ama buradaki doğru kod kalıbı nedir?

DÜZENLE:

İyi haber şu ki, C # 6.0 büyük olasılıkla hem catch hem de bloklarda bekleme çağrılarına izin verecektir .

Yanıtlar:


103

Güncelleme: C # 6.0, yakalamada beklemeyi destekler


Eski Cevap : Sen taşımak için bu kodu yeniden yazabilirsiniz awaitgelen catchbir bayrak kullanarak bloğu:

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
Teşekkürler svick, bu oldukça açık, daha iyi bir şey, eşzamansız ile daha bağlantılı bir şey var mı?
György Balássy

Böyle bir şeyin var olduğunu sanmıyorum.
svick

3
Sizin durumunuzda, görev devam ettirmelerini de kullanabilirsiniz. Ancak svickyanıtındaki kod, devamları kullanan koddan daha temizdir.
Stephen Cleary

16
Çağrı yığınını kaybetmeden istisnayı yeniden atmanız gerekirse, System.Runtime.ExceptionServices.ExceptionDispatchInfostatik sınıfı da kullanabilirsiniz . Sadece ExceptionDispatchInfo.Capture(ex)catch bloğunuzu çağırın ve yakalanan istisnai dönüş değerini yerel bir değişkende saklayın. capturedException.Throw()Eşzamansız kodunuzla işiniz bittiğinde, orijinal istisnayı uygun şekilde yeniden atacak olanı kullanabilirsiniz .
Etienne Maheu

müthiş teknik
Zia Ur Rahman


9

Bu işe yarıyor gibi görünüyor.

        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;

6

Bunu bir deneyin:

         try
        {
            await AsyncFunction(...);
        }

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

( Wait()Sonuna bakın )


4

C # 6.0 kullanın. bu bağlantıyı gör

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

1

Bir geri dönüş görevinde bekledikten sonra istisnayı yeniden atmak için kullandığım kalıp:

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

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

1

Lambda ifadesini aşağıdaki gibi kullanabilirsiniz:

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

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

        lambda(ex);
    }

Bu, mecbur async voidkalmadıkça kullanılmaması gereken lambda yapar .
svick

0

Sen koyabilirsiniz awaitbir takip catch bloğundan sonra labelve koyun gototry bloğundaki. (Hayır, gerçekten! Goto'lar o kadar da kötü değil!)


0

Benzer bir durumda, bir yakalama bloğunda bekleyemedim. Bununla birlikte, bir bayrak ayarlayabildim ve bayrağı bir if ifadesinde kullanabildim (aşağıdaki kod)

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

boolean exceptionFlag = false; 

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

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.