使用MessageBox在多线程应用程序中显示异常信息 [英] Using MessageBox to show exception information in multithreaded application

查看:288
本文介绍了使用MessageBox在多线程应用程序中显示异常信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用winform,并尝试使用MessageBox进行异常处理. 奇怪的是,MessageBox仅在关闭主窗体(下面的代码中为"Form1")后才会显示.

Hi I'm working with winform and trying to use MessageBox for exception handling. The weird thing here is, the MessageBox appears only after the main form ("Form1" in the code below) is closed.

public class Worker {
    /* edited (see below)
    public void doWork() {
        try {
            // do something
            client.Connect(serverAddress);
            stream = client.GetStream();
        }
        catch(Exception e) {
            MessageBox.Show(e.ToString(), 
                "This will not show up until Form1 is closed");
        }
    }
    */
}

public class Form1 {
    /* edited (see below)
     * public void threadProc() {
     *    Worker worker = new Worker();
     *    worker.doWork();
     * }
     */
     void button_Click(object sender, EventArgs e) {
        // create a thread that will end up throwing an exception
        Thread thread = new Thread(threadProc);
        thread.Start();
     }
}

使用MessageBox进行异常处理的更好方法是什么?

What could be a better way to use MessageBox for exception handling?

...因此我在UI线程中为MessageBox-ing 添加了一些代码,但问题仍然存在.

...So I added some codes for MessageBox-ing in the UI thread, but the problem remains.

public class WorkExceptionArgs : EventArgs {
    public Exception e;
    public WorkExceptionArgs (Exception e) { this.e = e; }
}
public partial class Worker1 { // renamed (Worker->Worker1)
    /* (edited) Now Worker1 doesn't trigger any event (see below)
       public event EventHandler<WorkExceptionArgs> workException;
    */
    public void doWork() {
        try {
            // do something
            client.Connect(serverAddress);
            stream = client.GetStream();
        }
        catch(Exception e) {
            /* (edited) suppose Worker1 never throws any exception (see below)
             *  // trigger event that will cause MessageBox-ing by UI thread
             *  workException(this, new WorkExceptionArgs(e));
             */
        }
    }
}
public partial class Form1 {
    public void threadProc() {
       Worker1 worker1 = new Worker();
      /* (edited) Now Worker1 never throws any exception
       * worker.workException += new EventHandler<WorkException>(worker_WorkException);
       */
       worker1.doWork();
       // (added) After doWork() is done, Form1 creates Worker2
       Worker2 w2 = new Worker2(this, this.form2);
       w2.workException += new EventHandlerArgs<WorkExceptionArgs>(form2.worker2_WorkException);
       w2.doSomeOtherWork();
    }
    /* public void worker_WorkException(object sender, WorkExceptionArgs eArg) {
     *   MessageBox.Show(eArg.e.ToString(), "Still not showing");
     * } */
    Form2 form2 = new Form2(); // (added) At first form2 is hidden (see below)
}


实际上,还有另一种形式和另一名工人.当Worker(Worker1)与服务器建立连接后,Form1隐藏(.Hide()),Form2显示(.Show()),Worker2开始使用Worker1建立的连接.


Actually there have been another form and another worker. Once Worker(Worker1) made connection to the server, Form1 hides (.Hide()), Form2 shows (.Show()), and Worker2 starts working with the connection Worker1 made.

public class Worker2 {
    Worker2(Worker1 w1, Form2 frm2) { this.w1=w1; this.frm2=frm2; }
    public Worker1 w1;
    public Form2 frm2;
    public event EventHandler<WorkExceptionArgs> workException;
    public void doSomeOtherWork() { // do some other, using data in Worker 1.
        try { // This will throw an exception
            BinaryFormatter formatter = new BinaryFormatter();
            MyObj mo = (MyObj)formatter.Deserialize(w1.getStream());
        }
        catch(Exception e) {
            workException(this, new WorkExceptionArgs(e));
        }
    }             
}

public class Form2 {
    public Form2(Form1 frm1) { // to switch from frm1 to frm2
        InitializeComponent();
        this.frm1 = frm1;
    }
    public Frm1 frm1 {get;set;}
    public void worker2_WorkException(object sender, WorkExceptionArgs ea) {
       MessageBox.Show(this, ea.e.ToString(), "SHOWS ONLY IF FORM2 IS CLOSED");
    }

}     

public partial class Form1 {
    delegate void switchWindow_Callback();
    public void switchWindow() { this.Hide(); form2.Show(); }
    public void switchWindowCb(object sender, EventArgs e) {
        if(this.InvokeRequired) {
            SwitchWindow_Callback hcb = new SwitchWindow_Callback(switchWindow);
            this.Invoke(hcb, new object[] {});
        }
        else { this.switchWindow(); }
    }
}

推荐答案

实际上,我敢打赌,MessageBox出现在主窗体的后面,在关闭它之前,您只是看不到它

Actually I'll bet the MessageBox is appearing behind the main form, and you just don't see it until you close it.

最好让UI线程(创建并拥有Form1的线程)执行MessageBox-ing.您要么要创建事件,要么要在worker类中有一个错误回调委托.

You'd be much better off letting the UI thread (the one that created and owns Form1) do the MessageBox-ing. You either want to make events, or otherwise have an error callback delegate in your worker class.

但是,BackgroundWorker可能值得在这里进行检查,而不是尝试自己动手做.假定这是一个致命异常,则可以保存和检索错误状态,并在线程完成时自动调用一个事件.

However, BackgroundWorker may be worth checking out here rather than trying to roll your own. Assuming it's a fatal exception, you can save and retrieve the error state, and you get an event automatically called when the thread finishes.

这篇关于使用MessageBox在多线程应用程序中显示异常信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆