C # yinelenen hata işleme kodunu azaltılması?

oy
32

Ben çok istisna yok, yolu istisna işleme çalışmaları ile tamamen mutlu ve deneyin / catch masaya getiriyor (vb gevşemek yığını), ancak süreç içinde OO modeli çok kırmak gibi görünüyor hiç.

Neyse, işte sorun şu:

Diyelim ki sarar veya ağa dosya IO işlemlerini (örneğin okuma ve yere bazı belirli UNC yolu bazı dosyaya yazma) içeren bazı sınıf var diyelim. Çeşitli nedenlerle o IO işlemleri başarısız istemiyorum, bu yüzden onlar bunları yeniden deneme başarısız olduğunu tespit ve başarılı olmaları kadar yeniden deneniyor tutmak veya eğer bir zaman aşımı ulaşır. Zaten örneğini ve vb deneme arasındaki mevcut iplik uyku ve zaman aşımı süresi dolduğunda belirlemek için kullanabileceğiniz kullanışlı bir RetryTimer sınıf var

Sorun bu sınıfın çeşitli yöntemlerde IO operasyonlarının bir grup varsa ve try-catch / yeniden deneme mantığında bunların her sarmak için ihtiyaç vardır.

İşte bir örnek kod parçacığı var:

RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
    try
    {
        // do some file IO which may succeed or fail
        success = true;
    }
    catch (IOException e)
    {
        if (fileIORetryTimer.HasExceededRetryTimeout)
        {
            throw e;
        }
        fileIORetryTimer.SleepUntilNextRetry();
    }
}

Peki, nasıl sınıfa boyunca her dosya IO operasyon için bu kodun en çoğaltarak engelleyebilirim? Benim çözümüm anonim temsilci bloklar ve kendisine geçirilen temsilci bloğunu infaz sınıfta tek yöntemi kullanmak oldu. Bu beni diğer yöntemlerde bu gibi şeyler yapmak için izin:

this.RetryFileIO( delegate()
    {
        // some code block
    } );

Ben biraz bu gibi ama arzulanan bir çok bırakır. Diğer insanların sorunu bu tür çözecek nasıl duymak istiyorum.

Oluştur 04/08/2008 saat 20:21
kaynak kullanıcı
Diğer dillerde...                            


4 cevaplar

oy
13

Bu Aspect Oriented Programlama bakmak için mükemmel bir fırsat gibi görünüyor. İşte iyi bir makale .NET AOP . Genel fikir ayrı bir sınıfa (x saat yani yeniden dene) çapraz fonksiyonel endişe ayıklamak istiyorum ve o zaman bu şekilde davranışlarını değiştirmeye gerek herhangi yöntemleri açıklama ediyorum olmasıdır. İşte (Int32 güzel bir uzantısı yöntemi ile) görünebilir nasıl

[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
  //.. code to just delete the archive
}
Cevap 05/08/2008 saat 10:43
kaynak kullanıcı

oy
4

Sadece merak, kendi yöntem arzulanan bırakır neler hissediyorsunuz? Bir anonim temsilci yerini alabilecek .. adında? temsilci, gibi bir şey

    public delegate void IoOperation(params string[] parameters);

    public void FileDeleteOperation(params string[] fileName)
    {
        File.Delete(fileName[0]);
    }

    public void FileCopyOperation(params string[] fileNames)
    {
        File.Copy(fileNames[0], fileNames[1]);
    }

    public void RetryFileIO(IoOperation operation, params string[] parameters)
    {
        RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
        bool success = false;
        while (!success)
        {
            try
            {
                operation(parameters);
                success = true;
            }
            catch (IOException e)
            {
                if (fileIORetryTimer.HasExceededRetryTimeout)
                {
                    throw;
                }
                fileIORetryTimer.SleepUntilNextRetry();
            }
        }
    }

    public void Foo()
    {
        this.RetryFileIO(FileDeleteOperation, "L:\file.to.delete" );
        this.RetryFileIO(FileCopyOperation, "L:\file.to.copy.source", "L:\file.to.copy.destination" );
    }
Cevap 04/08/2008 saat 21:07
kaynak kullanıcı

oy
2

İşte Geçenlerde yaptık. Muhtemelen başka bir yerde daha iyi yapılmıştır, ama oldukça temiz ve yeniden kullanılabilir görünüyor.

Şöyle bir yardımcı yöntem vardır:

    public delegate void WorkMethod();

    static public void DoAndRetry(WorkMethod wm, int maxRetries)
    {
        int curRetries = 0;
        do
        {
            try
            {
                wm.Invoke();
                return;
            }
            catch (Exception e)
            {
                curRetries++;
                if (curRetries > maxRetries)
                {
                    throw new Exception("Maximum retries reached", e);
                }
            }
        } while (true);
    }

Sonra benim uygulamada, ben her şeyin düzenli gitmesine c # 'ın Lamda ifade sözdizimini kullanın:

Utility.DoAndRetry( () => ie.GoTo(url), 5);

Bu benim yöntemini çağırır ve 5 kata kadar yeniden dener. Beşinci denemeden anda, orijinal istisnası yeniden deneme hariç iç rethrown edilir.

Cevap 13/09/2010 saat 03:25
kaynak kullanıcı

oy
2

Ayrıca daha OO yaklaşımı kullanabilirsiniz:

  • Hata işleme yapar ve beton işleri gerçekleştirmek için soyut bir yöntemini çağıran bir temel sınıf oluşturun. (Şablonu yöntem örneği)
  • Her işlem için somut sınıflar oluşturun.

Bu gerçekleştirmek operasyonun her tür adlandırma avantajına sahiptir ve size Komutanlığı desen verir - işlemler nesneler olarak temsil edilmiştir.

Cevap 07/08/2008 saat 12:30
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more