2011-09-04 75 views
0

我正在寻找一个规则来知道一个控件的哪些属性阻止从其它线程访问,而不是从它创建的线程访问它。 (比如说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; 
} 
: 
: 

感谢

回答

1

基本上任何其实施涉及到一个窗口句柄有与创建该窗口句柄的线程有亲和力。此限制是从底层Windows API继承的。

由于您无法知道实现,所以您必须假定所有事情都需要调用,除非文档专门调用异常。

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)); 
} 
+0

我觉得只是调用Invoke而不测试InvokeRequired更容易。 –