如何在视图上处理子线程异常?

时间:2018-01-23 20:06:52

标签: c# multithreading visual-studio-2010 exception-handling

我有一个小的MVC模式应用程序,它使用随机数据创建UDP数据包,并不断发送

主视图包含控制器:

public partial class MainForm : Form
    {
        private MainController controller;

        public MainForm(MainController c)
        {
            controller = c;
            InitializeComponent();
        } 
    //...
    }

主按钮单击事件调用最终将启动仿真的方法。我将它包装在try-cath块周围,这样我就可以在视图上显示任何异常

    public partial class MainForm : Form
    {
    //...
        private void btnInitiate_Click(object sender, EventArgs e)
        {
           try
           {
             controller.initiateEmulation(txtData.Text);
           }
           catch (Exception ex)
           {  
            MessageBox.Show(ex.Message + ex.StackTrace, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
           }
        }
     }


public class MainController:IMainController
{
    private Emulator model;

    public void initiateEmulation(string data)
    {
        model = new Emulator(data);
    }
}


public class Emulator
    {
        private Thread emulatorThread;
        public String data;

        public Emulator(string data)
        {
            this.data = data;
            emulatorThread = new Thread(Emulate);
            emulatorThread.Start();
        }

        private void Emulate()
        {
            //CREATES SOCKET
            while (true)
            {
              //SENDS RANDOMIZED DATA
            }       
        }
    }

问题是,我的try-catch块只捕获主线程中发生的异常

如何处理 emulatorThread 中的异常,以便我可以在视图中显示它们,与主线程中的相同?

1 个答案:

答案 0 :(得分:3)

有几种有趣的方法可以处理这类事情,不太确定这些是最佳实践"如果你不熟悉,你可能需要做一些研究与概念

首先是代表:

public class MainForm
    {
        private Emulator _emulator;

        public MainForm()
        {
            _emulator = new Emulator("data", HandleEmulatorException);
        }

        public void Render()
        {
            // Do other stuff
        }

        public void HandleEmulatorException(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public class Emulator
    {
        private Thread emulatorThread;
        public String data;
        public OnException OnError;

        public delegate void OnException(Exception e);

        public Emulator(string data, OnException onError)
        {
            OnError = onError;
            this.data = data;
            emulatorThread = new Thread(Emulate);
            emulatorThread.Start();
        }

        private void Emulate()
        {
            while (true)
            {
                try
                {
                    throw new Exception("Exception was thrown");
                }
                catch (Exception e)
                {
                    OnError(e);
                }
            }
        }
    }

这里我给模拟器一个委托,它可以在每次发生异常时调用,你也可以用函数/动作来执行:

public class MainForm
    {
        private Emulator _emulator;

        public MainForm()
        {
            _emulator = new Emulator("data", HandleEmulatorException);
        }

        public void Render()
        {
            // Do other stuff
        }

        public void HandleEmulatorException(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public class Emulator
    {
        private Thread emulatorThread;
        public String data;
        public Action<Exception> OnError;


        public Emulator(string data, Action<Exception> onError)
        {
            OnError = onError;
            this.data = data;
            emulatorThread = new Thread(Emulate);
            emulatorThread.Start();
        }

        private void Emulate()
        {
            while (true)
            {
                try
                {
                    throw new Exception("Exception was thrown");
                }
                catch (Exception e)
                {
                    OnError(e);
                }
            }
        }
    }

相同的概念,但你不必申报代表,事件是另一个:

public class MainForm
    {
        private Emulator _emulator;

        public MainForm()
        {
            _emulator = new Emulator("data");
            _emulator.OnError += HandleEmulatorException;
        }

        public void Render()
        {
            // Do other stuff
        }

        public void HandleEmulatorException(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public class Emulator
    {
        private Thread emulatorThread;
        public String data;
        public event OnException OnError;

        public delegate void OnException(Exception e);

        public Emulator(string data)
        {
            this.data = data;
            emulatorThread = new Thread(Emulate);
            emulatorThread.Start();
        }

        private void Emulate()
        {
            while (true)
            {
                try
                {
                    throw new Exception("Exception was thrown");
                }
                catch (Exception e)
                {
                    OnError(e);
                }
            }
        }
    }

同样的概念,但你不必传递一个代表,但你必须申报一个。

希望这有帮助