如何在另一个线程中调用方法?

时间:2011-05-13 20:42:07

标签: c# winforms multithreading

我有以下课程:

        using System;
        using System.Windows.Forms;

        namespace FastEyeControl
        {
            public partial class ConnectView : Form, IConnectView
            {
                private IConnectPresenter m_Presenter;

                public ConnectView()
                {
                    InitializeComponent();

                    m_Presenter = new ConnectPresenter(this);
                }

                public string Hostname
                {
                    get
                    {
                        return m_Hostname.Text;
                    }
                }

                public int Port
                {
                    get
                    {
                        return Convert.ToInt32(m_Port.Text);
                    }
                }

                public void ShowMessage(string message)
                {
                    MessageBox.Show(message,
                                    "Success",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                }

                public void ShowError(string message)
                {
                    MessageBox.Show(message,
                                    "ERROR!",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);
                }

                private void m_ConnectButton_Click(object sender, EventArgs e)
                {
                    m_Presenter.ConnectButtonPressed();
                }
            }
        }

演示者课程:

        using System;
        using System.Collections.Generic;

        namespace FastEyeControl
        {
            public class ConnectPresenter : IConnectPresenter
            {
                private IConnectView m_View;
                private IConnectModel m_Model;

                public ConnectPresenter(IConnectView view)
                {
                    m_View = view;
                    m_Model = FastEyeClient.Instance;
                }

                public void ConnectButtonPressed()
                {
                    m_Model.Connect(m_View.Hostname, m_View.Port);
                }

                private void ConnectionComplete(object sender, ConnectionEventArgs e)
                {
                    // Code here indicating whether connection was successful and informing the view.
                    // i.e...

                    if (e.IsConnected)
                    {
                        m_View.ShowMessage("Successfully connected.");
                    }
                    else
                    {
                        m_View.ShowError("Unable to connect.");
                    }
                }
            }
        }

模型代码在另一个线程中运行。问题是当我调用m_Model.Connect()时,我正在调用通常在主线程内的另一个线程中运行的代码(UI线程)。这不是数据库连接。这是到服务器的TCP / IP连接。如果我在模型中设置一个变量,那么我是从非线程安全的UI线程中做到的。

我知道使用用户控件,他们有InvokeRequired和Invoke / BeginInvoke操作来处理这种情况。但这仅适用于用户控件。我知道你不能在执行过程中中断另一个线程并告诉它调用另一个方法。我基本上希望非UI线程以某种方式调用Connect代码。

就像测试一样,我尝试使用委托(每当我想连接时触发事件),当我查看调试器时,Connect代码仍在UI线程中运行。

我本质上需要一个多线程事件队列。在这里实现我想要做的最好的方法是什么?谢谢!

2 个答案:

答案 0 :(得分:-1)

您可以使用BackgroundWorker

答案 1 :(得分:-1)

 public void ConnectButtonPressed()
            {
                var threadedTask = () => m_Model.Connect(m_View.Hostname, m_View.Port);
                threadedTask.BeginInvoke(null,null);
            }

毫无疑问,这将使用ThreadPool中的后台线程来完成工作。也许你曾试图直接调用委托,或者在其上调用Invoke();将同步执行委托。

现在,BeginInvoke很容易设置,但它有其局限性;你不能取消后台线程的执行,如果它抛出异常,你就无法在调用线程中捕获它。