Reputation: 1303
The post has been rewritten to better fit the current problem.
I have a button x:Name="selectVesselButton"
. On button click, it tries to establish a connection to a server, which takes a sec or two for to do. Originally, I wanted the button to be grayed out while it was downloading and deserializing the json file from the connection.
My old code (before async, and trying to update the button):
// disabling the button to prevent spam clicking.
string buttonText = selectVesselButton.Text;
selectVesselButton.IsEnabled = false;
selectVesselButton.Text = "loading...";
// retrieve data for speed page.
RetrieveData();
// redirect to next info block if build was successfull.
FocusSpeedblock();
// enabling the button again.
selectVesselButton.Text = buttonText;
selectVesselButton.IsEnabled = true;
The issue with this code was that the button visuals did not update until the RetrieveData() was finished, defeating the purpose of doing that at all. This was because the code for updating the interface and the code for downloading and deserializing the object were both on the same thread.
However, following Ivan's advice, I made the downloading and deserializing Async, which fixed this issue (more like moved it).
This works fairly well, but I am still having some trouble updating the interface automatically. I have some labels that need to be updated based on the json file output. The value of the labels update on the background, but only update visually once I interact with the labels (I.E. scrolling the scrollview they are on). Check edit 3 for more detail on that.
EDIT 3:
When the second thread is finished, it should call the UpdateSpeedLabels() and update some labels. However, they update in codebehind, without instantly updating the interface. They only update if I interact with those labels.
Upvotes: 1
Views: 608
Reputation: 9990
The preferred way of doing this on Xamarin is with data binding. As you opted out of this it is still possible.
What you need is to ensure that your long task is not running in the UI thread as it blocks it and prevent its updates. You do this by using Task.Run(() => { your task code });
. However you can't update your user interface inside the Task.Run
as it is not running on the UI thread and it would crash the app, so you need to use Device.BeginInvokeOnMainThread(() => { your UI code });
inside Task.Run
for that part.
Upvotes: 2