使用线程时发生错误

时间:2012-01-06 10:52:23

标签: .net multithreading c#-4.0

  

可能重复:
  Cross-thread operation not valid

我在下面的应用程序中使用线程有一个问题是两个简单的方法,这两个方法在按钮点击时被调用。
我希望首先运行插入方法并在第二次方法运行5秒后线程休眠5秒,并根据编码显示 但我面对这个错误:

  

跨线程操作无效:控制'lblDisplay'从其创建的线程以外的线程访问。

以下是代码:

private void button1_Click(object sender, EventArgs e)

    {

        Thread obj = new Thread(new ThreadStart(inserting));

        Thread obj1 = new Thread(new ThreadStart(insert));

        obj.Start();

        obj1.Start();

    }

public void inserting()
    {
        lblDisplay.Text = "inserting record......";
        Thread.Sleep(5000);
    }
    public void insert()
    {
        lblDisplay.Text = "Record successfully inserted";
    }

4 个答案:

答案 0 :(得分:2)

您只能在创建控件的同一个线程上修改控件。使用Control.Invoke修改您的控件:

lblDisplay.Invoke(() =>
{
    lblDisplay.Text = "inserting record......";
});

答案 1 :(得分:1)

您收到错误是因为您无法访问主UI线程(或WPF中的Dispatcher线程)以外的线程上的UI元素。如果您希望拥有一些状态更新系统,最好让一个进程在一个单独的线程上运行,然后回调到主UI线程以更新状态文本。例如:

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

private void Execute()
{
    UpdateStatus("Starting execution...");

    // ... Run some code ...

    UpdateStatus("Inserting record...");

    // Sleep for 5 seconds
    Thread.Sleep(5000);

    // ... Run record insertion code ...

    UpdateStatus("Record successfully inserted");
}

private void UpdateStatus(string status)
{
    // Make sure we're running on the UI thread
    if (this.InvokeRequired)
    {
        BeginInvoke(new Action<string>(UpdateStatus), status);
        return;
    }

    // Update the display text now we are running on the UI thread
    lblDisplay.Text = status;
}

注意:这是WinForms特有的答案。对于WPF,您使用CheckAccess()代替InvokeRequiredthis.Dispatcher.BeginInvoke(...)代替BeginInvoke(...)

答案 2 :(得分:0)

lblDisplay是在另一个线程上创建的,因此您需要一个委托来更改该值。请查看MSDN,并举例说明该怎么做。

答案 3 :(得分:0)

我也遇到了这个问题。我发布了解决方案here

这是因为您试图通过未创建Control的线程来修改UI控件。

像这样创建一个扩展

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
        else action.Invoke();
    }
 }

然后执行此操作

lblDisplay.Invoke(() => { lblDisplay.Text = "Record successfully inserted"; }); 

希望这会对你有所帮助。