一个控件由两个工作线程访问,第二个工作线程在第一个完成它对控件的工作之前。第二个线程(9)获取InvokeRequired == false,然后第一个线程(17)在子控件上调用.Refresh时获取异常。
这是预期的行为吗?究竟是什么导致线程将控件的InvokeRequired视为true / false?
最后,什么是一个很好的解决方案..锁定所有的调用语句,并让它们调用一个单独的方法(显然避免死锁)?
private void OnHistoryUpdate(object sender)
{
Console.WriteLine("<< Invoke? " + this.InvokeRequired + " " + Thread.CurrentThread.ManagedThreadId );
if (this.InvokeRequired)
this.Invoke(new Action<object>(OnHistoryUpdate), sender);
LoadTimeSeries(this.Interval);
Console.WriteLine(">> Invoke? " + this.InvokeRequired + " " + Thread.CurrentThread.ManagedThreadId);
}
输出:
<< Invoke? True Thread: 17
<< Invoke? False Thread: 9
>> Invoke? False Thread: 9
答案 0 :(得分:1)
您的代码更新了控件两次:
Invoke
的来电,该来电将另一个电话委托给OnHistoryUpdate
。这是安全的,因为Invoke
将执行封送到UI线程。Invoke
后。 Invoke
同步执行,当它返回您的代码时,将第二次调用LoadTimeSeries
,这次不安全(它不会再次检查InvokeRequired
)。我会更改下面的方法,并考虑使用BeginInvoke
代替工作线程不会阻塞。
private void OnHistoryUpdate(object sender)
{
Console.WriteLine("<< Invoke? " + this.InvokeRequired + " " + Thread.CurrentThread.ManagedThreadId );
if (this.InvokeRequired)
this.Invoke(new Action<object>(OnHistoryUpdate), sender);
else
LoadTimeSeries(this.Interval);
Console.WriteLine(">> Invoke? " + this.InvokeRequired + " " + Thread.CurrentThread.ManagedThreadId);
}
答案 1 :(得分:0)
如果在需要从线程调用而不使用调用的控件上调用Refresh,则应该会出现异常。确保你不这样做,你会没事的。这就是所需要的。