1

So I've been trying to solve this problem for hours now and I almost give up. There has to be a way to access a normal Label on a Xamarin C# code behind by another thread.

This is what I'm basically doing:

namespace Traktor
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class TrackerPage : ContentPage
    {
        public delegate void TrackedTimeUpdateHandler(double elapsedTime);    // Delegate to notify the TrackingPage of how much time elapsed
        private TimeTracker tracker;

        // Ctor, and other methods etc. are here
        // ...

        // Initialize the tracker and add handler to it (called in Ctor)
        void Initialize()
        {
            tracker = new TimeTracker();
            tracker.TrackedTimeUpdate += new TrackedTimeUpdateHandler(UpdateGUI);
        }

        // This method is called periodically by the inner thread of 'tracker'
        void UpdateGUI(double elapsedTime)
        {
            // Status label is a label on the page this refers to
            statusLabel.Text = String.Format("{0:F2}", elapsedTime); 
            // Throws exception: "Android.Util.AndroidRuntimeException: 'Only the original thread that created a view hierarchy can touch its views.'"
        }
    }
}

A seperate thread runs in TimeTracker tracker which constantly raises an event to notify this TrackerPage about how much time elapsed. Then the UpdateGUI(...)- method is called. That is only to set the text of the statusLabel to the elapsed time. Everything works like a charm. But I can not access the statusLabel.Text by another thread other than the UI- Thread itself.

I tried so much already and its annoying how nothing works because mostly something is missing or other things dont work out. For example, the statusLabel is not a Class that implements ISynchronizeInvoke, or I cant use the System.Windows.Forms.Control- Namespace. I dont know why.

So my question is: Is there a way to access the label (part of the UI on my ContentPage) and modify it from another thread (or in any way so that the elapsedTime can be displayed periodically)? I cant invokes and async doesnt seem to fit here. I really dont know how to get around this problem. Or maybe is there a Xamarin native way to invoke on the UI- thread?


What I've tried so far:

-> I cant use the System.Windows.Forms.Control- Namespace. I dont know why. Maybe because Xamarin doesnt want me to. So System.Windows.Forms.Control.Invoke and such are not accessible to me.

Vandrey
  • 531
  • 1
  • 8
  • 23
  • 1
    https://learn.microsoft.com/en-us/xamarin/essentials/main-thread – Jason Mar 26 '20 at 18:17
  • Thank you so much! I honestly dont know why I didnt stumble upon that. Can you make an answer or should I answer this so I can declare this question as closed? – Vandrey Mar 26 '20 at 18:43

1 Answers1

2

Essentials contains a helper class to force your code to execute on the main UI thread

MainThread.BeginInvokeOnMainThread(() =>
{
    // Code to run on the main thread
});
Jason
  • 86,222
  • 15
  • 131
  • 146
  • 1
    Funnily enough, I tried this and it didnt work. The seconds time I tried it this actually worked. I dont know but its weird. Anyways, thank you so much! This really helped me! – Vandrey Mar 27 '20 at 13:25