C# 另一个线程内窗体的访问控件

C# 另一个线程内窗体的访问控件,c#,multithreading,winforms,C#,Multithreading,Winforms,比如说,我在windows窗体上有两个按钮。 当我按下按钮1时,我在一个新线程th中使用一个名为wh的自动resetEvent来等待。 当我按下按钮2时,我执行wh.Set(),这样我的线程th就被解锁了。下面是我的课程来说明这一点: public partial class Form1 : Form { AutoResetEvent wh = new AutoResetEvent(false); Thread th; public Form1() {

比如说,我在windows窗体上有两个按钮。 当我按下按钮1时,我在一个新线程th中使用一个名为wh的自动resetEvent来等待。 当我按下按钮2时,我执行wh.Set(),这样我的线程th就被解锁了。下面是我的课程来说明这一点:

public partial class Form1 : Form
{
    AutoResetEvent wh = new AutoResetEvent(false);
    Thread th;

    public Form1()
    {
        InitializeComponent();
    }

    public void button1_Click(object sender, EventArgs e)
    {
        th = new Thread(thread);
        th.Start();
    }

    public void thread()
    {
        MessageBox.Show("waiting..");
        wh.WaitOne();
        MessageBox.Show("Running..");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        wh.Set();
    }
}
这是我们想要的。但我的问题是,我无法从我的线程访问标签或任何其他控件

public partial class Form1 : Form
{
    AutoResetEvent wh = new AutoResetEvent(false);

    public Form1()
    {
        InitializeComponent();
    }

    Thread th;

    public void button1_Click(object sender, EventArgs e)
    {
        th = new Thread(thread);
        th.Start();
    }

    public void thread()
    {
        label1.Text = "waiting..";
        wh.WaitOne();
        label1.Text = "running..";
    }

    private void button2_Click(object sender, EventArgs e)
    {
        wh.Set();
    }
}
运行此命令时出现错误,表示label1是从另一个线程访问的

那么,在不阻塞主线程的情况下,如何访问第二个线程中的控件,或者修改代码以更改
wh.WaitOne
的位置呢?
代码示例非常感谢

之所以会发生这种情况,是因为标签是在不同的线程上创建的,您不能直接更改它。我建议你用


阅读有关Contol的
invokererequired
属性和
Invoke
方法的信息。感谢您如此快速地回答,这可能是重复的!这是可行的,但是否有某种解决办法来缩短这一时间?主要是因为在我的真实代码中,我有很多控件要多次访问。好吧,在本文中,我建议您使用而不是本机线程,因为它是为在这种情况下使用而设计的
 AutoResetEvent wh = new AutoResetEvent(false);
    Thread th;

    private delegate void SetLabelTextDelegate(string text);
    public Form1()
    {
        InitializeComponent();
    }
    public void thread()
    {
        // Check if we need to call BeginInvoke.
        if (this.InvokeRequired)
        {
            // Pass the same function to BeginInvoke,
            this.BeginInvoke(new SetLabelTextDelegate(SetLabelText),
                                             new object[] { "loading..." });
        }
        wh.WaitOne();

    }

    private void SetLabelText(string text)
    {
        label1.Text = text;
    }