SwtichToContext does not return to original thread

Viewed 60

I'm working with an API that can only access its objects on the main thread, so I need to create a new thread to be used for my GUI and then swap back to the original thread for any lengthy calculations involving the API.

So far I have the following code:

[<EntryPoint; STAThread>]
let main _ =
    Debug.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] - Inital thread")
    let initCtx = SynchronizationContext.Current
            
    let uiThread = new Thread(fun () ->
        let guiCtx = SynchronizationContext.Current
        Debug.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] - New UI thread")
        async{
            do! Async.SwitchToContext initCtx
            Debug.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] - Back to initial thread")
            // Lengthy API calculation here
            do! Async.SwitchToContext guiCtx
            Debug.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] - Back to UI thread")

        } |> Async.RunSynchronously        
    )
    uiThread.SetApartmentState(ApartmentState.STA)
    uiThread.Start()
    1

However when I run this I get the output:

[1] - Inital thread
[4] - New UI thread
[5] - Back to initial thread
[5] - Back to UI thread

So it doesn't seem to be switching contexts the way I would expect. How can I switch back to the original thread after creating a new thread this way?



I have tried calling SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher)) first to ensure that the original thread has a valid SynchronizationContext but that causes the program to exit at the Async.SwitchToContext lines without throwing any exception.

I have also tried using Async.StartImmediate instead of RunSynchronously with the same result.

If I try both of these at the same time then the program just freezes up at the Async.SwitchToContext lines instead of exiting out.

0 Answers
Related