【问题标题】:WinForms exception interceptorWinForms 异常拦截器
【发布时间】:2017-09-14 15:42:21
【问题描述】:

我正在使用带有 WinForms 的 ABP 框架,我需要确定拦截异常并记录此信息的最佳方法。

My WinForms 是一个多文档界面 (MDI) 应用程序。我在 Program.cs 中添加了一个HandleException,这样当应用程序抛出异常时,我就可以将它记录在日志文件中。但是如果我在ApplicationService 中遇到异常,则此异常由 ABP 处理,不会被扔回 WinForms,并且不会在日志文件中写入任何内容。

我是否需要实现一些接口才能拥有像 MVC/Angular 应用这样的经典日志记录?

更新

我发现问题与异步操作有关。通常我会打电话:

await _service.GetProducts();

如果抛出异常,主线程不会拦截它。如果我切换到:

AsyncHelper.RunSync(() => _service.GetProducts());

然后主线程拦截错误。

【问题讨论】:

    标签: winforms asynchronous exception-handling interceptor aspnetboilerplate


    【解决方案1】:

    因为异常是在另一个线程中引发的,所以您必须处理应用程序域的未处理异常。将异常处理程序插入应用程序的起点。对于 win 表格,我猜你可以使用 program.cs

    static class Program
    {
      [STAThread]
      static void Main(string[] argv)
      {
        try
        {
          AppDomain.CurrentDomain.UnhandledException += (sender,e)
          => HandleException(e.ExceptionObject);
    
          Application.ThreadException += (sender,e)
          => HandleException(e.Exception);
    
    
          Application.Run(new MainWindow());
        }
        catch (Exception ex)
        {
          HandleException(ex);
        }
      }
    
      static void HandleException(object exception) {
        var ex= exception as Exception;
        if (ex== null) {
             ex= new NotSupportedException("Unhandled exception: " + exceptionObject.ToString());
        }
    
        //you can log exception here -> ex.ToString();
      }
    }
    

    【讨论】:

    • @Albert 感谢您的建议,但这样您就无法拦截异步异常
    【解决方案2】:

    好吧,经过一番调查和谷歌搜索,我找到了这个 MSDN 解释 Asynchronous Programming - Async from the Start

    根据本文,我将程序开始更改为异步代码。 我需要多花点钱,因为打开内部表单时我在 Mdi Form 上

    Form1 childForm = Globals.Bootstrapper.IocManager.Resolve<Form1>();
            childForm.MdiParent = this;
            var formAsync = childForm.InitializeAsync();
            FormExtension.HandleExceptions(formAsync);
            childForm.Show();
    

    我添加静态类来拦截错误表单Abp

    public static async void HandleExceptions(Task task)
        {
            try
            {
                await Task.Yield(); //ensure this runs as a continuation
                await task;
            }
            catch (Exception ex)
            {
                //deal with exception, either with message box
                //or delegating to general exception handling logic you may have wired up 
                //e.g. to Application.ThreadException and AppDomain.UnhandledException
                var log = Globals.Bootstrapper.IocManager.IocContainer.Resolve<ILogger>();
                LogHelper.LogException(log, ex);
                //Exception handling...
                MessageBox.Show("Ops!" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    
                //Application.Exit();
            }
        }
    

    现在我的日志文件以正确的方式填充

    【讨论】:

    • 这看起来不像是解决问题的便捷方式。这里的拦截在哪里?您只需创建一个围绕任务的尝试捕获。在拦截中,您必须在实际功能之前或之后做一些事情!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多