I am using SynchronizationContext
as a means to synchronize to the GUI thread, for WinForms and WPF. Recently I ran into an issue with the old style async callbacks:
private void Button_Click(object sender, RoutedEventArgs e)
{
uiContext = SynchronizationContext.Current;
var cl = new TcpClient();
cl.BeginConnect("127.0.0.1", 22222, ConnectedCallback, null);
}
public void ConnectedCallback(IAsyncResult result)
{
if (SynchronizationContext.Current != uiContext)
uiContext.Post(x => MyUIOperation(), null);
else
MyUIOperation();
}
public void MyUIOperation()
{
Title = "Connected";
}
private SynchronizationContext uiContext;
This will throw an exception, because the SynchronizationContext.Current
in the callback function is equal to the captured one, and therefore the UI operation is executed in the worker thread of the callback.
Using this exact same code in WinForms works as I had expected.
For now as a workaround, I am capturing the current ManagedThreadId
instead and compare it in the callback. What is correct way to handle this?
Update:
I should add that I am modifying a very old existing class that currently uses the following construct:
if (control.InvokeRequired())
control.BeginInvoke(SomeFunction);
else
SomeFunction();
I am trying to remove the WinForms dependency, without having much impact on the clients of this class. The SomeFunction()
is raising events, so if I just call uiContext.Send() or uiContext.Post() , the order of execution is changed since Post() will always queue the call, and Send() will always block.
Also, this is just a very small piece of code to show the root of my issue. In reality the function doing the Post() can be called from the main thread.
This is targeting .NET 4.0