我有一个设置为使用MEF的Caliburn.Micro应用程序。 在首次加载的ViewModel中,我遍历MEF加载的各种程序集中的类(接口)。 在其中一个类中,有一个定义为异步任务的方法:
private async Task SomeAsyncMethod()
如果此方法抛出异常,则它永远不会被引导程序中的OnUnhandledException
覆盖或其他任何地方捕获。
如何定义全局异常处理程序来捕获此异常?
按照此处所述实施:https://caliburnmicro.codeplex.com/wikipage?title=Customizing%20The%20Bootstrapper
另外添加包含要加载到Configure覆盖的附加程序集的文件夹,并添加OnUnhandledException
protected override void Configure()
{
AggregateCatalog aggregateCatalog = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(ConfigurationManager.AppSettings["ExternalComponents"]));
_container = new CompositionContainer(aggregateCatalog);
CompositionBatch batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(_container);
_container.Compose(batch);
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<IShell>();
}
protected override void OnUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
// Exceptions from async methods are not caught here
MyLogger.Error(e.Exception, "Unhandled exception");
e.Handled = true;
}
public class MainViewModel : IShell
{
[ImportMany]
private IEnumerable<IMyMefClass> _myMefClasses;
protected override void OnViewLoaded(object view)
{
foreach (IMyMefClass instance in _myMefClasses)
{
instance.Start();
}
}
}
[Export(typeof(IMyMefClass))]
public class MyMefClassImplementation : IMyMefClass
{
public void Start()
{
SomeAsyncMethod();
}
private async Task SomeAsyncMethod()
{
throw new Exception("This is never caught");
}
}
如上所述,问题仍然是如何定义一个全局异常处理程序来捕获此异常?
答案 0 :(得分:1)
另一个解决方案是,juste重写你的OnViewLoaded方法:
protected override void OnViewLoaded(object view)
{
var runningTasks = _myMefClasses.Select(m=>m.Start()).ToArray();
try
{
Task.WaitAll(runningTasks);
}
catch(AggregateException ex)
{
//Any exception raised by a task will be in ex.InnerExceptions
}
}
此解决方案还具有让所有任务并行运行的优势。
答案 1 :(得分:0)
最简单的解决方案:
public class MyMefClassImplementation : IMyMefClass
{
public void Start()
{
try
{
await SomeAsyncMethod();
} catch(Exception ex) {
throw ex
}
}
// ...
}