Search code examples
c#multithreadinguser-interface.net-2.0monodevelop

Call method on UI thread from background in .net 2.0


I am using MonoDevelop (.net 2.0) to develop a iOS and Android app. I use BeginGetResponse and EndGetResponse to asynchronously do a webrequest in a background thread.

IAsyncResult result = request.BeginGetResponse(new AsyncCallback(onLogin), state);

However, the callback onLogin does seem to still be running on a background thread, no allowing me to interact with the UI. How do I solve this?

Can see that there are Android and iOS specific solutions but want a cross-platform solution.

Edit: From mhutch answer I've got this far:

IAsyncResult result = request.BeginGetResponse(o => {
            state.context.Post(() => { onLogin(o); });
        }, state);

Where state contains a context variable of type SynchronizationContext set to SynchronizationContext.Current

It complains that Post requires two arguments, the second one being Object state. Inserting state gives the error

Argument `#1' cannot convert `anonymous method' expression to type `System.Threading.SendOrPostCallback' (CS1503) (Core.Droid)

Solution

  • Both Xamarin.iOS and Xamarin.Android set a SynchronizationContext for the GUI thread.

    This means you get the SynchronizationContext.Current from the GUI thread and pass it to your callback (e.g via the state object or captured in a lambda). Then you can use the context's Post method to invoke things on the main thread.

    For example:

    //don't inline this into the callback, we need to get it from the GUI thread
    var ctx = SynchronizationContext.Current;
    
    IAsyncResult result = request.BeginGetResponse(o => {
        // calculate stuff on the background thread
        var loginInfo = GetLoginInfo (o);
        // send it to the GUI thread
        ctx.Post (_ => { ShowInGui (loginInfo); }, null);
    }, state);