1

我有一个“userdetails”类,它有一个名为“detailschanged”的事件。每当用户详细信息更改时,都会引发它。
当我在我的新表单中创建一个新的“userdetails”对象(objUserDetails)时,我将订阅事件“detailschanged”以指示用户有关数据更改的信息。

objUserDetails.detailschanged += InformtoUser

InformtoUser 是一种新形式的方法。在 InformtoUser 方法中,我正在访问表单的控件(比如标签的文本属性)。
访问控件时,我收到“跨线程操作”错误。
如何避免这种跨线程操作?

4

2 回答 2

3

这里的问题是线程安全:

对 Windows 窗体控件的访问本质上不是线程安全的。如果您有两个或更多线程操作控件的状态,则可能会强制控件进入不一致的状态。其他与线程相关的错误是可能的,例如竞争条件和死锁。确保以线程安全的方式执行对控件的访问非常重要。

在不使用 Invoke 方法的情况下从创建控件的线程以外的线程调用控件是不安全的。

Control.Invoke在对 Windows 窗体控件进行任何跨线程调用时需要使用。

例如:

delegate void SetTextCallback(string text);

private void SetText(string text)
{
    if (textBox.InvokeRequired)
    {    
        SetTextCallback d = new SetTextCallback(SetText);
        this.Invoke(d, new object[] { text });
    }
    else
    {
        textBox.Text = text;
    }
}

或者:

this.Invoke((MethodInvoker) delegate {
    this.textBox.Text = "Some text here";
});

有关详细信息,您应该参阅如何:对 Windows 窗体控件进行线程安全调用

于 2012-07-07T10:31:57.827 回答
1

UI 控件只能从 UI 线程更新。如果您正在使用 WinForms,您应该这样做:

mycontrol.Invoke((MethodInvoker)(() =>
{
  mycontrol.Text="some text";
}));

如果您在 WPF 中,那么您应该使用调度程序:

myControl.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => myControl.Text = ""));
于 2012-07-07T10:32:36.180 回答