Forum Xamarin.Forms

Cannot set some properties of a Label within a different thread (Task.Run) in Xamarin PCL

BobHowardBobHoward USMember ✭✭

Maybe this doesn't have anything to do with Xamarin, just tesing my understanding of tasks in general I think. I have a task that creates a label among other things and it is in a task so I can keep the activityindicator spinning while it is running. Setting certain properties cause it to fail, for example (PCL) project:

private void Wtf()
{
Task.Run(() =>
{
var oLbl = new Label() { Text = "Order" }; // This works
var oLbl2 = new Label() { FontSize = 10, Text = "Order" }; // This fails
});
}

The error is "The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))" which seems pretty straight forward, but I don't understand how FontSize could be a different thread than the Text property;
Both 'Text' and 'FontSize' are properties of Label. Must be different somehow...?

Posts

  • NMackayNMackay GBInsider, University mod
    edited July 2017

    @BobHoward

     Device.BeginInvokeOnMainThread(() =>
                    {
                        var oLbl2 = new Label() { FontSize = 10, Text = "Order" };
                    });
    

    Probably because your trying to update something UI specific while not on the UI thread.

  • BobHowardBobHoward USMember ✭✭
    edited July 2017

    Mmmm, I kind of see that, not sure I understand why the Text property would not also be UI specific; it is displayed on the screen as well.

    Is there a rule of thumb on what properties are/not UI specific so I can get a feel for what cannot be done in a Task? I have a fairly long running loop that is creating labels with different fonts, etc., so I guess I have to lock the main thread for that... I'm guessing Device.BeginInvokeOnMainThread should not be called in a loop :(

  • NMackayNMackay GBInsider, University mod
    edited July 2017

    Does that solve your issue?

    I just tend to update data bindings on background threads (I just use async where possible and only spin up a new thread is I need to). Fontsizes, colors etc I set with data triggers or converters where I need to so that's done on the UI thread.

    I don't have a specific technical answer why it allows you change Text, I'd have to look further into the control but as a rule of thumb you'd use BeginInvokeOnMainThread when changing the UI from a non UI thread.

  • BobHowardBobHoward USMember ✭✭

    Yes, not updating the FontSize property solves the issue.

    For now, I am maintaining a list of Labels in my loop then switching over to the main thread to set the sizes, etc. in another loop before they get displayed. I'm guessing that will be more efficient than initializing the label within BeginInvokeOnMainThread in my loop but just a guess, not sure of the internals.

  • JohnHardmanJohnHardman GBUniversity mod

    @BobHoward - There is a confirmed bug for this - https://bugzilla.xamarin.com/show_bug.cgi?id=39399

    My expectation would be that you could set, from another thread, properties of Views that are not yet part of the UI hierarchy of a page, but having done so, would have to hook them into the UI hierarchy on the UI thread. FontSize doesn't meet that expectation currently.

  • dinobdinob USUniversity ✭✭✭

    Thanks @NMackay . I also run on this issue and it is all clear and make sense. What I find strange (the reason I havent seen it before is because I dont work on UWP) is that on Android or IOS (Xamarin.Forms), you dont have to call Device.BeginInvokeOnMainThread. But on UWP, you do; otherwise, you run into the issue above. Adding Device.BeginInvokeOnMainThread however does not hurt as all 3 platforms work fine with it.

Sign In or Register to comment.