2013-04-04 12 views
9

Należy wziąć pod uwagę następujący kod, który używa podstawowej biblioteki zadań z funkcją AnulowanieTokenSource. Uruchamia wątek, który wypełnia słownik ceną i odczytuje dane z bazy danych serwera SQL. Gwint kończy się po około 10 minutach i co 2 godziny jest ponownie uruchamiany, wywołując Anuluj jako pierwszy, jeśli wątek nadal działa.Wyjątek podczas działania System.Threading.Tasks.Task

private CancellationTokenSource mTokenSource = new CancellationTokenSource(); 

internal Prices(Dictionary<string, Dealer> dealers) 
{ 
    mDealers = dealers; 
    mTask = Task.Factory.StartNew 
      (() => ReadPrices(mTokenSource.Token), mTokenSource.Token); 
} 

internal void Cancel() 
{ 
    mTokenSource.Cancel(); 
} 
private void ReadPrices(CancellationToken ct) 
{ 
    using (SqlConnection connection = 
      new SqlConnection(ConfigurationManager.AppSettings["DB"])) 
    { 
     connection.Open(); 
     var dealerIds = from dealer in mDealers.Values 
         where dealer.Id != null 
         select dealer.Id; 
     foreach (var dealerId in dealerIds) 
     { 
      if (!ct.IsCancellationRequested) 
      { 
       FillPrices(connection); 
      } 
      else 
       break; 
     } 
    } 
} 

Teraz w pewnym momencie aplikacja ulega awarii z następującym wyjątkiem w dzienniku zdarzeń.

Zastosowanie: Engine.exe Framework Wersja: v4.0.30319 Opis: Proces został zakończony z powodu nieobsługiwanego wyjątku. Informacje wyjątek: System.AggregateException Stos: w System.Threading.Tasks.TaskExceptionHolder.Finalize()

Musi mieć do czynienia z kodem tutaj, ponieważ biblioteka Zadania nie jest używany nigdzie indziej, ale nie mogę dowiedzieć się, co jest nie tak z kodem. Czy ktoś ma pojęcie, co może być nie tak?

+4

Niestety, nie rejestrujesz wystarczająco dużo w dzienniku. Wyrażenie "AggregateException" może zawierać dowolną liczbę innych wyjątków, a są to wyjątki, które z większym prawdopodobieństwem zawierają przydatne informacje pomocne w diagnozowaniu problemu. –

+0

Również "Gwint kończy się po około 10 minutach i co 2 godziny ... na wypadek, gdyby wątek nadal działał." - Wygląda na to, że już glosujesz nad problemem, który powinieneś badać - zwykle zajmuje to 10 minut, ale czasami trwa jeszcze po 2 godzinach ... –

+0

istnieje program klienta, który może anulować wątek w dowolnym momencie i ponownie uruchomić tak więc odwołanie jest zdecydowanie potrzebne – Laurijssen

Odpowiedz

19

Zadania, które lubią czuć słuchane. Wygląda na to, że coś nie jest szczęśliwe. Dostaniesz „ostatniej szansy”, aby wysłuchać go, choć:

TaskScheduler.UnobservedTaskException += (sender, args) => 
{ 
    foreach (var ex in args.Exception.InnerExceptions) 
    { 
     Log(ex); 
    }    
    args.SetObserved(); 
}; 

Uwaga ta nie jest przeznaczona jako fix - jest on przeznaczony do pozwalają zobaczyć co Task eksploduje iz jakim błędzie. SetObserved() uniemożliwi to zabicie twojej aplikacji. Ale fix tutaj jest idealnie:

  • niech nie rzucać zadania,
  • lub upewnij się, że jesteś tam, aby sprawdzić status zadania później

To jest prawdopodobnie nie jest zadowolony z wykrycia anulowania. IIRC preferowanym sposobem na to byłoby:

foreach(...) { 
    if(ct.IsCancellationRequested) { 
     // any cleanup etc 
     ct.ThrowIfCancellationRequested(); 
    } 
    ... 
} 

lub prościej, jeśli nie ma potrzeby czyszczenia, po prostu:

foreach(...) { 
    ct.ThrowIfCancellationRequested(); 
    ... 
} 

Podobnie mogło być tylko wyjątkiem dostępu do danych. Istnieje dowolny numer wyjątków, które mogą się zdarzyć podczas rozmowy z bazą danych. Limit czasu, zakleszczenie, nie można połączyć itp.

Powiązane problemy