Виключення (-ів) Завдання не спостерігалися ні в режимі "Очікування завдання", ні в доступі до його властивості "Виняток". Як результат, незабезпеченим винятком став


100

Що це означає і як це вирішити?

Я використовую завдання TPL.

Вся помилка

Виключення (-ів) Завдання не спостерігалися ні в режимі "Очікування завдання", ні в доступі до його властивості "Виняток". Як результат, непомічене виключення було скинуто потоком фіналізатора.

на System.Threading.Tasks.TaskExceptionHolder.Finalize ()

mscorlib

Відповіді:


158

Якщо ви створили Завдання, і ви ніколи не дзвоните task.Wait()або не намагаєтеся отримати результат Task<T>, коли завдання збирається сміттєзбірником, воно зірве вашу програму під час завершення. Докладніше див. На сторінці MSDN про обробку винятків у TPL .

Найкращий варіант тут - "обробляти" виняток. Це можна зробити через продовження - ви можете приєднати продовження до завдання, а також увімкнути / проковтнути / тощо виняток, що виникає. Це забезпечує чіткий спосіб реєстрації винятків із завдання, і їх можна записати як простий метод розширення, тобто:

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);
}

З урахуванням вищезазначеного ви можете запобігти зірванню програми та реєстрації програми будь-яким завданням за допомогою:

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

Крім того, ви можете підписатися на TaskScheduler.UnobservedTaskException і обробити його там.


17
Для додаткової розваги створіть статичний метод заглушки Offв класі, названому як чотирибуквене слово на ваш вибір, і використовуйте це для свого продовження. Допомагає боротися з деякими невдоволеними розчаруваннями від цього винятку.
Aaronaught

1
@MonsterMMORPG Так - ви, в основному, повинні десь ловити або обробляти виняток . Поки ви десь впораєтеся, ваша основна проблема піде.
Рід Копсей

1
Чи не можливо, що завдання може скинути виняток до того, як буде здійснено дзвінок на ContinueWith?
Тім Сильвестр

1
@TimSylvester Рамка все одно буде відображати його через продовження, навіть якщо це станеться "до" продовження додається
Рід Копсей

32
Важлива примітка. Це потрібно лише для .Net 4.0. Обробку винятків було змінено за замовчуванням, .net 4.5щоб не зруйнувати додаток . Детальніше дивіться у розділі Обробка винятків із завдань у .NET 4.5
i3arnon

43

Впевнений; це означає, що його Taskдоопрацьовували після того, як він був залишений на вивезення сміття, але сама задача провалилась. Є два виправлення:

  • справлятися із завданнями не вдалося безпосередньо (використовувати ContinueWith(...)для підписки, перевірку .IsFaultedта .Exceptionвведення Taskв параметрі)
  • обробляти TaskScheduler.UnobservedTaskExceptionподію та відзначати спостережуване (дзвінок e.SetObserved()після реєстрації помилки)

4
+1 - З одним доповненням - якщо ваше продовження не робить нічого, окрім перевірки IsFaulted, ви можете скористатися параметром OnlyOnFaultedпродовження та уникнути ручної перевірки ...
Reed Copsey

насправді це сталося там, де я викликав публічну статичну функцію всередині завдання tpl. використання спробувати catch дозволить вирішити цю проблему? мені справді потрібно створити ще одне завдання і чекати його? спасибі
MonsterMMORPG

4
+1 за згадку , що SetObservedна UnobservedTaskExceptionEventArgsпотреби називати.
Джеймс Вебстер

-17

Спробуйте це:

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
Його один ??? Що ви маєте на увазі? Чи можете ви пояснити, що ваша відповідь сприяє відповідям поки що?
Герт Арнольд

Ви тільки що створили нове завдання, продовживши яке потім не вдасться і потрапите в ту саму ситуацію.
Роберт Тейлор

Це рішення здається трохи заплутаним. Думаю, ви ненавмисно приховали б функціональність без жодної вигоди.
Велокітас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.