Xamarin Adventures: Consistent Cross-Platform Multi-Threading

Hi there readers! Like I said in the last post, I wanted to write something about Xamarin, and now that it’s open source you might be more interested than before in taking this framework for a spin.

Xamarin is a .NET framework used to build Android, iOS, Mac and Windows Phone apps. It uses C# language features to map Android and iOS APIs and also has a top level abstraction called Xamarin Forms to achieve the most common user story scenarios.

I will start these series of posts, with one question that I think is a keystone to all subsequent development issues you might find when dealing with multi-threading.


When I tap the screen and trigger a Command, Xamarin automagically uses threads to execute lambdas or methods. So,

What’s the Main Thread of a ViewModel?

This one seems obvious but, is it really? When you tap a Xamarin.Forms control bound to an ICommand, it triggers an Action from the Main Thread, the UI Thread, blocking everything in the foreground until the Action is complete. Here’s a screenshot of the IDE executing code from the UI Thread (the one highlighted and having ID = 1). Even though it’s taken from an Application class, the ViewModel behaves the same way, having the Commands defined in the constructor.

Screen Shot 2016-04-05 at 2.22.31 PM
Xamarin.Forms Button Command starts in Thread #1

You need to keep track of your execution context and current thread, specially when dealing with background tasks. It’s easy to go back to the UI Thread (thread #1) from a background one; you just need to call Device.BeginInvokeOnMainThread and place another method or a lambda.

MessagingCenter considerations

According to Xamarin docs, Xamarin.Forms MessagingCenter enables view models and other components to communicate with without having to know anything about each other besides a simple Message contract.

Messaging Center is really helpful, and there’s a very nice video about it, and backgrounding with Xamarin Forms from Xamarin University.

Anyways, here’s where the multi-threading rears its ugly head and you need to have a Batman’s plan for not loosing context and/or crash the app for doing something unwanted in the UI Thread.

Should I keep track of the Thread ID Number?

Not at all, the Thread ID is a bit unreliable in Xamarin Forms. Let’s see the difference between ManagedThreadId and IsBackground fields within CurrentThread.

Consider the following Subscribe method:

 MessagingCenter.Subscribe<string> (this, "Hello World Message", async (string obj) => {
                if (Thread.CurrentThread.IsBackground)
                    Device.BeginInvokeOnMainThread (async () =>
                                                    await Application.Current.MainPage.DisplayAlert ("Hello World Message", "You were in a Bg Thread" + obj, "Ok, Got it!"));
                else
                    await Application.Current.MainPage.DisplayAlert ("Hello World Message", obj, "Ok, Got it!");
            });

This subscribe method is asking if the Thread is a background one or not, because you can’t actually depend on asking for it’s ID if the thread is in a ThreadPool. This is a workaround, of course, the best practice here would be to have a clear understanding of where you are in the thread context, and separate the background process from the UI part like in the examples shown in Xamarin University’s backgrounding lecture.

Here’s another screenshot of the IDE showing the inconsistency of Thread IDs:

Screen Shot 2016-04-05 at 5.05.48 PM
ManagedThreadId is different than Thread ID in Xamarin Studio Toolbar

This is another reason to have a clear and unified way of starting background tasks and ensure context consistency across the whole application.

Final Thoughts

The ViewModel starts its context within the UI Thread. If you want to ensure thread consistency with Xamarin Forms, my advice is to:

  • Call ViewModel methods from UI Thread
  • If you have a recursive method in the ViewModel, make sure it’s been called from the right Thread (use Device.BeginInvokeOnMainThread if necessary)
  • Call MessagingCenter.Send from UI Thread
  • Use Task class to start long running processes in the background
  • Nest Device.BeginInvokeOnMainThread call within a background task to refresh the UI

The example code can be found in Xamarin Forms AppCompat Toolbar Example GitHub’s repository. This sample is very simple and doesn’t use ViewModels, so I’ll try to update it with XAML and a VM next time.

Stay tuned for more coding adventures!

Cheers!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s