Unhandled exception in managed thread

76 views
Skip to first unread message

Сергей Калинец

unread,
Feb 25, 2011, 6:27:55 PM2/25/11
to Kiev ALT.NET
Всем привет!

Продолжая дискуссию на афтепати про то, проглатывается ли исключение в
потоке, привожу пруфлинк (VS 2010):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ThreadExceptions
{
class Program
{
static void Main(string[] args)
{
Console.Out.WriteLine("1 -
ThreadPool.QueueUserWorkItem()");
Console.Out.WriteLine("2 - Thread.Start() (IsBackground =
false)");
Console.Out.WriteLine("3 - Thread.Start() (IsBackground =
true)");
Console.Out.Write("Select case (1-3): ");
int i = Convert.ToInt32(Console.ReadLine());
Console.Out.WriteLine("i = {0}", i);

new List<Action> {Do1, Do2, Do3}[i -1]();

Console.ReadLine();
}

private static void Do1()
{
ThreadPool.QueueUserWorkItem(_ => { throw new
Exception(); }, null);
}

private static void Do2()
{
var thread = new Thread(() => { throw new Exception(); });
thread.IsBackground = false;
thread.Start();
}

private static void Do3()
{
var thread = new Thread(() => { throw new Exception(); });
thread.IsBackground = true;
thread.Start();
}
}
}

У меня все три метода наглухо падают. Вариант с таймером не привожу,
потому что там используется тот же ThreadPool.

Мысли MS по этому поводу тут: http://j.mp/hPa3Dy

Mike Chaliy

unread,
Mar 1, 2011, 1:27:05 AM3/1/11
to Kiev ALT.NET
Ндя, хорошо что печень не поставил на то что неупадет ;). Ща
протестим.

Mike Chaliy

unread,
Mar 1, 2011, 1:35:57 AM3/1/11
to Kiev ALT.NET
Протестил, действительно падает. Шейм он ми ;).

Serhiy Kalinets

unread,
Mar 1, 2011, 4:14:46 AM3/1/11
to kieva...@googlegroups.com, Mike Chaliy
А что скажут F# братья? Может там все по другому (как с замыканиями)? 

--
Regards,
Serhiy Kalinets


2011/3/1 Mike Chaliy <mi...@chaliy.name>

kluGe

unread,
Mar 1, 2011, 5:56:15 AM3/1/11
to kieva...@googlegroups.com, Mike Chaliy
Вот это тоже падает. В консоли будет один из фелов, ниразу не видел оба или done. Как только упал поток упал и процесс. Теперь осталось под w3wp хостом перепроверить.
Как мы мало знаем про потоки :)

[<EntryPoint>]
let main (args: string []) =
    
    let failer = [async{ failwith "FAIL1" };async{ failwith "FAIL2" }]
    failer
    |> Async.Parallel
    |> Async.Ignore
    |> Async.Start
    
    printfn "done"
    Console.In.ReadLine() |> ignore
    0

Serhiy Kalinets

unread,
Mar 1, 2011, 6:01:19 AM3/1/11
to kieva...@googlegroups.com, kluGe, Mike Chaliy
Asp.net по идее ловит все исключения, но в другом потоке может и не заметить. Но там все просто -- если даже w3wp упадет, IIS его переподнимет. Это ж обычное дело, как recycling.

--
Regards,
Serhiy Kalinets


2011/3/1 kluGe <klu...@gmail.com>

kluGe

unread,
Mar 1, 2011, 6:09:57 AM3/1/11
to kieva...@googlegroups.com, kluGe, Mike Chaliy
Если бы это был recycling то невозможно было-бы потерять данные из нескольких поток и получить все остальные. А именно из-за этого случая я с тобой не согласился.
Процесс порождал 60000 воркеров, но получилал в результате 59996 ответов от них. После обработки исключений всё стало на свои места, но это IIS и F#. 

Vladimir

unread,
Mar 1, 2011, 8:33:58 AM3/1/11
to Kiev ALT.NET
Появится в консоли done или нет - зависит только от планировщика,
наверняка утверждать ничего нельзя.
А вот только одно сообщение об ошибке - особенность поведения
комбинатора Async.Parallel: при возникновении первого исключения он
пытается за'cancel'ить оставшиеся выполняющиеся workflows, повторные
исключения игнорируются.

Если надо получить все исключения, то можно например оборачивать
workflow в Async.Catch либо переходить к Tasks

open System.Threading.Tasks

try
Task.WaitAll <|
[|
for i in 1..10 do
yield Async.StartAsTask(async { failwithf "%d" i}) :>
_
|]
with
:? System.AggregateException as ae ->
for e in ae.InnerExceptions do
printfn "%s" e.Message

Serhiy Kalinets

unread,
Mar 1, 2011, 8:38:53 AM3/1/11
to kieva...@googlegroups.com
С тасками там вроде тоже не все просто -- тоже нужно обрабатывать исключения в колбеках (вроде бы). Но тут я уже говорю по памяти -- сам не проверял. :)

--
Regards,
Serhiy Kalinets

Vladimir Matveev

unread,
Mar 1, 2011, 8:48:47 AM3/1/11
to kieva...@googlegroups.com
при использовании WaitAll\WaitAny- исключение будет выброшено в ожидающем потоке. Кроме того, исключение можно обработать, передав continuation (ContinueWith) либо подписавшись на TaskScheduler.UnobserverdTaskException.

1 марта 2011 г. 15:38 пользователь Serhiy Kalinets <kali...@gmail.com> написал:

kluGe

unread,
Mar 1, 2011, 9:11:22 AM3/1/11
to kieva...@googlegroups.com
Вопрос был не в отлове исключений, а есть-ли случаи когда исключение втихую закончит выполнение потока или асинка. В консоли похоже не бывает так.

Serhiy Kalinets

unread,
Mar 1, 2011, 7:23:52 PM3/1/11
to kieva...@googlegroups.com, kluGe
В windows сервисе тоже такого не бывает. По умолчанию (как и в консоли).

--
Regards,
Serhiy Kalinets


2011/3/1 kluGe <klu...@gmail.com>
Reply all
Reply to author
Forward
0 new messages