A control is accessed by two worker threads, the 2nd before the first has completed it’s work on the control. The second thread (9) gets InvokeRequired == false, and the first thread (17) then gets the exception when calling .Refresh on a child-control.
Is this expected behavior? What exactly causes a thread to see a control’s InvokeRequired as true/false?
And finally, what would be a good solution.. Put a lock on all invoke statements, and make them call a separate method instead (to avoid deadlock obviously) ?
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);
}
output:
<< Invoke? True Thread: 17
<< Invoke? False Thread: 9
>> Invoke? False Thread: 9
Your code updates the control twice:
Invoke, which delegates another call toOnHistoryUpdate. This is safe becauseInvokemarshals execution to the UI thread.Invoke.Invokeexecutes synchronously and when it returns your code will callLoadTimeSeriesa second time, this time unsafely (it doesn’t checkInvokeRequiredagain).I would change the method as below, and also consider using
BeginInvokeinstead so the worker thread doesn’t block.