Normalnie z asynchronicznych delegatów jeśli metoda delegowany zgłasza wyjątek wątek jest zakończony, a wyjątek zostanie ponownie rzucony w kodzie wywołującym tylko gdy dzwonisz EndInvoke
.
Dlatego podczas korzystania z asynchronicznego uczestnika (BeginInvoke
) należy zawsze dzwonić pod numer EndInvoke
.Tego również nie należy mylić z Control.BeginInvoke
, który można wywołać w sposób przypominający ogień i zapomnienie.
Wcześniej powiedziałem normalnie, ponieważ istnieje możliwość, aby stwierdzić, że wyjątek powinien zostać zignorowany, jeśli metoda delegata zwróci puste. Aby to zrobić, musisz oznaczyć metodę atrybutem OneWay
.
Jeśli uruchomisz poniższy przykład, otrzymasz wyjątek tylko podczas wywoływania willNotIgnoreThrow.EndInvoke
.
static void Throws()
{
Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);
throw new ApplicationException("Test 1");
}
[OneWay]
static void ThrowsButIsIgnored()
{
Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);
throw new ApplicationException("Test 2");
}
static void Main(string[] args)
{
Console.WriteLine("Main: {0}", Thread.CurrentThread.ManagedThreadId);
var willIgnoreThrow = new Action(ThrowsButIsIgnored);
var result1 = willIgnoreThrow.BeginInvoke(null, null);
Console.ReadLine();
willIgnoreThrow.EndInvoke(result1);
Console.WriteLine("============================");
var willNotIgnoreThrow = new Action(Throws);
var result2 = willNotIgnoreThrow.BeginInvoke(null, null);
Console.ReadLine();
willNotIgnoreThrow.EndInvoke(result2);
}
-1: Twoja odpowiedź sugeruje również, że wywołanie 'ThreadPool.QueueUserWorkItem' z metodą, która zgłasza wyjątek spowoduje, że wyjątek zostanie zjedzony przez framework, co nie jest prawdą w wersji 2.0 i późniejszej. –
@ João Angelo: ThreadPool w ogóle nie będzie generował wyjątków, na przykład nowe zadanie C# 4.0 nie będzie generowało wyjątków, ale w metodzie tast.Wait, podobnie jak metoda EndInvoke. –
Jesteś ABSOLUTNIE w porządku. Po prostu jestem głupi! –