21

当您在 C# 中进行数据绑定时,更改数据的线程也会导致控件发生更改。但是如果这个线程不是创建控件的那个线程,你会得到一个非法跨线程操作异常。

有没有办法防止这种情况发生?

4

4 回答 4

5

您应该能够执行以下操作:

if (control.InvokeRequired)
{
    control.Invoke(delegateWithMyCode);
}
else
{
    delegateWithMyCode();
}

InvokeRequired 是 Controls 上的一个属性,用于查看您是否在正确的线程上,然后 Invoke 将在正确的线程上调用委托。

更新:实际上,在我上一份工作中,我们做了这样的事情:

private void SomeEventHandler(Object someParam)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SomeEventHandlerDelegate(SomeEventHandler), someParam);
    }

    // Regular handling code
}

这消除了对 else 块的需要,并且收紧了代码。

于 2008-08-05T07:51:54.727 回答
2

由于我没有测试用例,我不能保证这个解决方案,但在我看来,类似于用于更新不同线程中的进度条(使用委托)的场景在这里适合。

public delegate void DataBindDelegate();
public DataBindDelegate BindData = new DataBindDelegate(DoDataBind);

public void DoDataBind()
{
    DataBind();
}

如果数据绑定需要由特定线程完成,那么让该线程完成工作!

于 2008-08-05T07:56:53.140 回答
0

在 WPF 和 Silverlight 中,绑定基础结构负责切换到 UI 线程。

于 2008-08-08T16:19:17.923 回答
0

如果线程调用是“非法的”(即 DataBind 调用会影响未在调用它的线程中创建的控件),那么您需要创建一个委托,以便即使 DataBind 的决策/准备没有完成控制创建线程,它们的任何结果修改(即DataBind())都将是。

你会像这样从工作线程调用我的代码:

this.BindData.Invoke();

然后,这将导致原始线程进行绑定,这(假设它是创建控件的线程)应该工作。

于 2008-08-05T08:06:42.840 回答