RescueAttribute が壊れている状況を見つけたと思います。または、コルーチンを間違って使用している可能性があります。
次のような ViewModel があります。
[Rescue("Rescue")]
class MyViewModel
{
//... left out some bus-logic code here ...
public void Login()
{
yield return Show.Busy();
//the following line will also cause the problem, just like AsyncResult
//yield return Show.MessageBox("Test");
yield return new AsyncResult(() => _server.Login());
//throw new Exception("Aww, snap!");
yield return Show.NotBusy();
}
public void Rescue(Exception exc)
{
//Show a messagebox or something
}
}
AsyncResult は次のように実装されます。
using Exec = Caliburn.PresentationFramework.Invocation.Execute;
public class AsyncResult : IResult
{
private readonly Action _function;
public AsyncResult(Action function)
{
_function = function;
}
public void Execute(ResultExecutionContext context)
{
Exec.OnBackgroundThread(delegate
{
try
{
_function();
}
catch (Exception exc)
{
Exec.OnUIThread(() => Completed(this, new ResultCompletionEventArgs { Error = exc, WasCancelled = true }));
return;
}
Exec.OnUIThread(() => Completed(this, new ResultCompletionEventArgs()));
});
}
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
}
上記の ViewModel で例外のコメントを外すと、Rescue は例外の処理に失敗します。
これは Caliburn のバグですか、それとも AsyncResult の実装が間違っていますか?
yield の前に例外を置いて AsyncResult を返すと、Rescue は問題なく動作します。また、例外が非同期スレッドでスローされた場合でも、レスキューは機能します!
編集: AsyncResult の代わりに Show.MessageBox を使用して、同じ問題を再現することもできます。