简体   繁体   中英

How do I invoke a method in another thread?

I have the following classes:

        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();
                }
            }
        }

The presenter class:

        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.");
                    }
                }
            }
        }

The model code runs in another thread. The problem is that when I call m_Model.Connect(), I'm calling code that's usually running in another thread within the main thread still (the UI thread). This is not a database connection. This is a TCP/IP connection to a server. If I set a variable within the model, then I am doing this from the UI thread which is not thread safe.

I know that with user controls, they have InvokeRequired and Invoke/BeginInvoke operations that will handle this situation. But that is for user controls only. I know you can't just interrupt another thread in the middle of its execution and tell it to call another method instead. I basically want the non-UI thread to call the Connect code somehow.

Just as a test, I tried using a delegate (fire off an event whenever I want to connect) and when I look in the debugger, the Connect code is still running in the UI thread.

I need a multi-threaded event queue essentially. What's the best way to achieve what I want to do here? Thanks!

您可以使用BackgroundWorker

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

This will, no question, use a background thread from the ThreadPool to do the work. Maybe you had tried to call the delegate directly, or called Invoke() on it; that will execute the delegate synchronously.

Now, BeginInvoke is simple to set up, but it has its limitations; you cannot cancel execution of the background thread, and if it throws an exception you cannot catch it in the invoking thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM