Bir Görevin istisnaları, Görevi Bekleyerek veya İstisna özelliğine erişerek gözlemlenmedi. Sonuç olarak, gözlenmeyen istisna


100

Bu ne anlama geliyor ve nasıl çözülür?

TPL görevlerini kullanıyorum.

Bütün hata

Bir Görevin istisnaları, Görevi Bekleyerek veya İstisna özelliğine erişerek gözlemlenmedi. Sonuç olarak, gözlemlenmeyen istisna, sonlandırıcı iş parçacığı tarafından yeniden ortaya çıktı.

System.Threading.Tasks.TaskExceptionHolder.Finalize ()

mscorlib

Yanıtlar:


158

Bir Görev oluşturursanız ve hiçbir zaman arama yapmazsanız task.Wait()veya a sonucunu almaya çalışmazsanız Task<T>, görev çöp toplayıcı tarafından toplandığında, sonlandırma sırasında uygulamanızı yırtar. Ayrıntılar için , MSDN'nin TPL'de Özel Durum İşleme hakkındaki sayfasına bakın .

Buradaki en iyi seçenek, istisnayı "ele almaktır". Bu, devam ettirme yoluyla yapılabilir - göreve bir devam ekleyebilir ve oluşan istisnayı günlüğe / yutabilir / vb. Bu, görev istisnalarını günlüğe kaydetmek için temiz bir yol sağlar ve basit bir uzantı yöntemi olarak yazılabilir, yani:

public static void LogExceptions(this Task task)
{
    task.ContinueWith( t =>
    {
         var aggException = t.Exception.Flatten();
         foreach(var exception in aggException.InnerExceptions)
             LogException(exception);
    }, 
    TaskContinuationOptions.OnlyOnFaulted);
}

Yukarıdakilerle, herhangi bir görevin uygulamayı yırtmasını ve günlüğe kaydetmesini şu yolla önleyebilirsiniz:

Task.Factory.StartNew( () => 
   { 
       // Do your work...
   }).LogExceptions();

Alternatif olarak, TaskScheduler.UnobservedTaskException'a abone olabilir ve orada işleyebilirsiniz.


17
Daha fazla eğlence için, Offseçtiğiniz dört harfli kelime olarak adlandırılan bir sınıfta statik bir saplama yöntemine sahip olun ve bunu tümünü yakalama devamlarınız için kullanın. Bu özel istisnadan kaynaklanan bazı bastırılmış hayal kırıklıklarıyla mücadele etmeye yardımcı olur.
Aaronaught

1
@MonsterMMORPG Evet - Temelde bir yerde istisnayı yakalamanız veya halletmeniz gerekir . Bunu bir yerde hallettiğiniz sürece, temel sorununuz ortadan kalkacaktır.
Reed Copsey

1
Görevin ContinueWith çağrısı yapılmadan önce bir istisna atması mümkün değil mi?
Tim Sylvester

1
@TimSylvester Çerçeve, devam ettirme eklenmeden "önce" gerçekleşse bile, devamın haritasını çıkarmaya devam edecek
Reed Copsey

32
Önemli not: Bu yalnızca için gereklidir .Net 4.0. İstisna işleme, varsayılan olarak uygulamayı yırtmamak.net 4.5 için değiştirildi . Daha See .NET 4.5 Görev İstisna İşleme
i3arnon

43

Elbette; Taskçöp toplamaya bırakıldıktan sonra bir sonuçlandırıldı, ancak görevin kendisi başarısız oldu. İki düzeltme var:

  • görevleri (kullanımı ile doğrudan başarısız ele ContinueWith(...)abone ve kontrol .IsFaultedve .Exceptionilgili Taskparametresinde)
  • idare TaskScheduler.UnobservedTaskExceptionolayı ve (çağrı gözlemlenmiştir işaretlemek e.SetObserved()hatayı giriş yaptıktan sonra)

4
+1 - Bir ilaveyle - devam etme IsFaultedOnlyOnFaulted
durumunuz

aslında bu, bir tpl görevinin içinde bir public static işlevi olarak adlandırdığım yerde oldu. try catch kullanmak bu sorunu çözer mi? Gerçekten başka bir görev oluşturup beklemem gerekiyor mu? teşekkürler
MonsterMMORPG

4
Söz için 1 SetObservedüzerine UnobservedTaskExceptionEventArgsihtiyaçlarına çağrılacak.
James Webster

-17

Bunu dene:

public static void ThrowFirstExceptionIfHappens(this Task task)
{
    task.ContinueWith(t =>
    {
        var aggException = t.Exception.Flatten();
        foreach (var exception in aggException.InnerExceptions)
        {
            throw exception; // throw only first, search for solution
        }
    },
    TaskContinuationOptions.OnlyOnFaulted); // not valid for multi task continuations
}

public static Task CreateHandledTask(Action action) 
{
    Task tsk = Task.Factory.StartNew(action);
    tsk.ThrowFirstExceptionIfHappens();
    return tsk;
}

5
Biri ??? Ne demek istiyorsun? Cevabınızın şu ana kadar cevaplara ne katkısı olduğunu açıklayabilir misiniz?
Gert Arnold

devam ederek yeni bir görev yarattınız ve bu daha sonra başarısız olacak ve aynı duruma girecek.
Robert Taylor

Bu çözüm biraz karışık görünüyor. Herhangi bir kazanç sağlamadan işlevselliği istemeden saklayacağınızı düşünüyorum.
Velocitas
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.