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


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.