1.System.InvalidOperationException:“线程间操作无效: 从不是创建控件“”的线程访问它。”
这个问题是我们在子线程中更新UI时常常发生的问题。
解决方法1:
在更新UI前用this.Invoke()将里面的内容放在当前控件所在的线程上执行。除了用this.Invoke() ,也可以用RichTextBox.Invoke()等等其他控件。
如下所示:
this.Invoke(new EventHandler(delegate
{
RichTextBox.Select(RichTextBox.TextLength, 0);
//滚动到控件光标处
RichTextBox.ScrollToCaret();
RichTextBox.AppendText(info + Environment.NewLine);
}));
解决方法2:
通过UI线程的SynchronizationContext的Post/Send方法更新。
定义一个变量(可定义为一个静态的变量,所有地方都可使用):
public static SynchronizationContext m_SyncContext = null;
尽量在窗体构造函数或FormLoad事件中给变量赋值为当前线程。
m_SyncContext = SynchronizationContext.Current;
需要转线程的地方:
public static void Write(string info)
{
m_SyncContext.Post(AddRichText, info);//将要转线程的代码放在AddRichText中
}
private static void AddRichText(object info)//传入参数必须为object
{
RichTextBox.Select(RichTextBox.TextLength, 0);
//滚动到控件光标处
RichTextBox.ScrollToCaret();
RichTextBox.AppendText(info + Environment.NewLine);
}
2.System.InvalidOperationException:“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”
第一个问题解决后常常会导致这个问题,这是由于电脑执行的太快,控件的初始化未完成造成。
可以等待控件初始化完成后再执行(不建议这样的方式),
while (!this.IsHandleCreated)
{
;
}
this.Invoke(...);
或者直接跳过,但是这个就是不会执行了,如果逻辑是不能跳过的,建议出现问题1的时候选择解决方法2。
if( this.IsHandleCreated )
{
this.Invoke(...);
}