C# 在另一个线程中访问窗体窗口

C# 在另一个线程中访问窗体窗口,c#,.net,multithreading,C#,.net,Multithreading,如何在另一个线程中的窗口的列表框中添加条目。 我的问题是,我必须要有线程。 一个工作线程,完成所有实际工作,一个线程用于显示状态信息的窗口。 我试图在构造函数中将窗体窗口作为参数传递,但是当我调用它时,我得到了一个异常 下面是我的一些代码来说明这个问题: public partial class Mainform : Form { private string db = String.Empty; private string password = String.Empty;

如何在另一个线程中的窗口的列表框中添加条目。 我的问题是,我必须要有线程。 一个工作线程,完成所有实际工作,一个线程用于显示状态信息的窗口。 我试图在构造函数中将窗体窗口作为参数传递,但是当我调用它时,我得到了一个异常

下面是我的一些代码来说明这个问题:

public partial class Mainform : Form
{
    private string db = String.Empty;
    private string password = String.Empty;
    private string sqlinifile = String.Empty;
    DatabaseListener dbListener;
    StatusWindow statusWindow;

    public Mainform()
    {
        //
        // The InitializeComponent() call is required for Windows Forms designer support.
        //
        InitializeComponent();

        //
        // TODO: Add constructor code after the InitializeComponent() call.
        //
        db = "EWAG";
        password = "secret";
        sqlinifile = "C:\\Programme\\Unify\\Team Developer 5.2\\sql.ini";
        textBoxDB.Text = db;
        textBoxPwd.Text = password;
        textBoxSqlIni.Text = sqlinifile;

        statusWindow = new StatusWindow();
        dbListener = new DatabaseListener(statusWindow);
    }

    public void threadStarter()
    {
        this.dbListener.startSynchronizing(5);

    }
    void Button1Click(object sender, EventArgs e)
    {
        this.db = textBoxDB.Text;
        this.password = textBoxPwd.Text;
        this.sqlinifile = textBoxSqlIni.Text;

        if (dbListener.connectToDatabase(db,"sysadm", password, sqlinifile)) 
        {
            this.Hide();
            statusWindow.Show();
            Thread synchronizer = new Thread(new ThreadStart(threadStarter));
            synchronizer.Start();

        }
    }       

}
使用Luke的
.Invoke()

说真的,要从另一个线程与窗体上的某些控件进行对话,您必须
Invoke()
某些方法,以便与窗口句柄对话的属性设置器被序列化到主UI线程及其消息泵

或者,使用主UI线程上的计时器收集信息并将其放入列表框

或者使用混合方法,一个线程收集数据,将其放入未绑定到UI的队列中,然后使用计时器将其出列并在表单上显示数据。我偶尔使用它,因为接收数据的速率太大,会阻塞用户界面。

使用
.Invoke()
,Luke

说真的,要从另一个线程与窗体上的某些控件进行对话,您必须
Invoke()
某些方法,以便与窗口句柄对话的属性设置器被序列化到主UI线程及其消息泵

或者,使用主UI线程上的计时器收集信息并将其放入列表框


或者使用混合方法,一个线程收集数据,将其放入未绑定到UI的队列中,然后使用计时器将其出列并在表单上显示数据。我偶尔使用它,因为接收数据速率太大,它会阻塞UI。

用于调用任何应该接触UI的代码。

用于调用任何应该接触UI的代码。

除了使用Invoke(),检查是否需要使用要修改的对象的invokererequired属性调用当前线程。您可以使用下面代码中的模式创建委托并使方法线程安全

    private delegate void LogLineDelegate(string ShortText, string LongText);
    private void LogLine(string ShortText, string LongText)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new LogLineDelegate(LogLine), new object[] { ShortText, LongText });
            return;
        }
        sbLog.Append(string.Format("{0:MM-dd-yy} {0:HH:mm:ss.fff} - {1}: {2}.\r\n", DateTime.Now, ShortText, LongText));
        textBoxLog.Text = sbLog.ToString();
    }

除了使用Invoke()之外,请检查是否需要使用要修改的对象的InvokeRequired属性调用当前线程。您可以使用下面代码中的模式创建委托并使方法线程安全

    private delegate void LogLineDelegate(string ShortText, string LongText);
    private void LogLine(string ShortText, string LongText)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new LogLineDelegate(LogLine), new object[] { ShortText, LongText });
            return;
        }
        sbLog.Append(string.Format("{0:MM-dd-yy} {0:HH:mm:ss.fff} - {1}: {2}.\r\n", DateTime.Now, ShortText, LongText));
        textBoxLog.Text = sbLog.ToString();
    }