Hi, I am experiencing a strange behaviour with InvokeOnMainThread
.
In particular I have a function that is called (with a very small temporal distance) by two different threads, and in which I need to update some UI controls so I do it in the Action
passed to InvokeOnMainThread
. The strange thing is that the two Actions are not run sequentally, so one after another, but "concurrently".
In order to make things clearer, let us consider the following function, that has a similar structure to mine, where InnerFunction
contains the methods that modify the UI controls.
void OuterFunction(object sender, EventArgs e) { ... InvokeOnMainThread(() => { var guid = Guid.NewGuid(); Console.WriteLine("STEP 1" + " GUID: " + guid); InnerFunction(); Console.WriteLine("STEP 2" + " GUID: " + guid); }); }
Let's say we have two Threads, ThreadA
and ThreadB
and that ThreadA calls OuterFunction
some milliseconds before ThreadB
. What I would expect is that the action passed to InvokeOnMainThread
by ThreadA
will finish its execution before the Action
passed by ThreadB
starts executing. Practically an output like this:
STEP 1 GUID_A STEP 2 GUID_A STEP 1 GUID_B STEP 2 GUID_B
Instead, I am observing that the Action
passed by ThreadB
starts executing before the other Action
has ben completed, so I get an output like the following:
STEP 1 GUID_A STEP 1 GUID_B STEP 2 GUID_A STEP 2 GUID_B
or even:
STEP 1 GUID_A STEP 1 GUID_B STEP 2 GUID_B STEP 2 GUID_A
How is this behaviour happening?
[I have edited the answer so I have attached a project that shows the problem]
Answers
Interesting, if you log out the thread id at the same time I presume they all say 1, right?
If you replace the call to InnerFunction with a threadbound delay, does it behave the same? InvokeOnMainThread should only occur when the UI thread goes back to its event processing loop, so maybe something in your InnerFunction is allowing that...
[EDIT] I could be talking doodoo, the Xamarin documention on this says InvokeOnMainThread does not return until it has completed the action...
I have attached a sample project that exhibits the issue. I have managed to understand that the cause of the behaviour is related to a method I have created (
ToNSAttributedString
in the attached project), but I am not sure how.Yes, if I log the id they all say 1. I am not sure about what do you mean by "threadbound delay", but if instead of the call to the function, I do idle work (like having a for loop with ten thousand loops), the output is as expected.
But if the inner function is the following one, I have problems:
One can for example call it in the following way:
And this causes the unexpected behaviour. I am attaching again the project, because I deleted the last attachment. If you run the project and click the button, you can see that the order of execution is not as expected.
And, yes, the documentation says that InvokeOnMainThread is blocking, and that is true. Unfortunately this doesn't help in my case