跨线程操作异常的规则?

时间:2011-09-04 05:34:14

标签: c# multithreading

我正在寻找一条规则来了解Control的哪些属性阻止从其创建的线程以外的其他线程进行访问。 (比如UI线程)换句话说,为什么可以从任意线程访问Control的某些属性而其他一些线程拒绝它?

:
:
{
    Thread thrd1 = new Thread(DoSomething);
    thrd1.Start();
}
:
:
void DoSomething()
{
    // There is no problem..
    dataGridView1[columnIndex1, rowIndex1].Value = "Access is free!";
    dataGridView1[columnIndex1, rowIndex1].Style.BackColor = Color.Red;

    // Cross-Thread operation exception would be thrown..
    dataGridView1.Rows[rowIndex1].Visible = false;
}
:
:

由于

2 个答案:

答案 0 :(得分:1)

基本上任何实现涉及窗口句柄的东西都与创建该窗口句柄的线程具有亲缘关系。此限制继承自基础Windows API。

由于您无法了解实现,因此您必须假设所有内容都需要调用,除非文档专门调用异常。

答案 1 :(得分:0)

虽然某些属性不需要同步访问,但您不应该依赖此行为,除非属性明确的文档指示可以从任何线程访问属性。使用Control.InvokeRequired有条件地执行跨线程调用。

例如:

void DoSomething()
{
    if (dataGridView1.InvokeRequired)
        dataGridView1.Invoke(new Action(DoSomethingImpl));
    else
        DoSomethingImpl();
}

void DoSomethingImpl()
{
    dataGridView1[columnIndex1, rowIndex1].Value = "Access is free!";
    dataGridView1[columnIndex1, rowIndex1].Style.BackColor = Color.Red;

    dataGridView1.Rows[rowIndex1].Visible = false;
}

我喜欢像这样封装这个功能:

public static object AutoInvoke(
    this ISynchronizedInvoke self,
    Delegate del,
    params object[] parameters)
{
    if (self == null)
        throw new ArgumentNullException("self");

    if (del == null)
        throw new ArgumentNullException("del");

    if (self.InvokeRequired)
        return self.Invoke(del, parameters);
    else
        return del.DynamicInvoke(parameters);
}

然后DoSomething()成为:

void DoSomething()
{
    dataGridView1.AutoInvoke(new Action(DoSomethingImpl));
}