我在一个成员中得到了'跨线程操作无效',但在另一个成员中却没有,并且都属于同一个窗体,我相信这是同一个UI线程。这些成员是uxServerGroup
和uxServerListen
。当我更改uxServerGroup.ValuesSecondary.Heading
上的文本时,它工作正常,我没有遇到交叉线程异常。但是当我尝试启用uxServerListen
按钮时,我确实会得到一个。 为什么?为什么我没有为表单中的所有成员获得“跨线程操作无效”?
我应该注意到这两个组件都属于Krypton Toolkit,它们不是标准的Windows窗体。
下面的代码我有一个样本:
MainForm.cs:
public partial class MainForm : Form {
public MainForm() {
InitializeComponent();
SomeClass.ObjectStateChanged += new ObjectStateEventHandler(SomeClass_ObjectStateChanged);
}
private void uxServerListen_Click(object sender, EventArgs e) {
uxServerListen.Enabled = false;
ClassHandler ch = ClassHandler();
ch.Initialize();
}
private void SomeClass_ObjectStateChanged(Enum e1, Enum e2) {
switch(e1) {
case E1.TypeA:
HandleTypeAObjectChanges(e1);
break;
case E1.TypeB:
HandleTypeBObjectChanges(e2);
break;
}
}
private void HandleTypeAObjectChanges(Enum e2) {
switch(e2) {
case E2.ModeA:
uxServerGroup.ValuesSecondary.Image = Resources.StatusSuccess16;
break;
case E2.ModeB:
uxServerGroup.ValuesSecondary.Image = Resources.StatusFailure16;
uxServerListen.Enabled = true;
break;
}
}
}
SomeClass.cs:
public delegate void ObjectStateEventHandler(Enum e1, Enum e2);
public static class SomeClass {
public static event ObjectStateEventHandler ObjectStateChanged;
internal static E1 e1;
internal static void ObjectStateChanged(Enum e2) {
if(ConnectionStateChanged != null) {
ConnectionStateChanged(e1, e2);
}
}
}
ClassHandler.cs:
public class ClassHandler {
public ClassHandler() {
// (...)
}
public void Initialize() {
Thread thread = new Thread(new ThreadStart(SomeMethod));
thread.Start();
}
private void SomeMethod() {
SomeClass.ObjectStateChanged(E2.ModeB);
}
}
很多搜索后,我结束了固定这样的:
private void SomeClass_ObjectStateChanged(Enum e1, Enum e2) {
if(InvokeRequired) {
Invoke(new MethodInvoker(() => {
switch(e1) {
case E1.TypeA:
HandleTypeAObjectChanges(e2);
break;
case E1.TypeB:
HandleTypeBObjectChanges(e2);
break;
}
}));
}
}
作为一个额外的问题,有人可以解释我这个(内MethodInvoker
的东西):
new MethodInvoker(() => { /* (...) */ })
因为只有当Winforms *知道*它是不安全的时候才会生成异常。它通过你的代码使用Handle属性来知道。像Enabled属性设置器一样。它不知道你自己添加的任何属性都是线程不安全的,它假定你做对了。 – 2012-03-20 01:20:24