2

I'm starting my adventure with mobile developing and already faced a problem. I know in WPF I would use BackgroundWorker to update the UI, but how does it work with Android using Xamarin?

I've found many advises but none of these worked for me. The code below won't change the text while the rest is being executed, it just awaits and performs all at once, which isn't what I want.

private void Btn_Click(object sender, System.EventArgs e)
{
    RunOnUiThread(() => txt.Text = "Connecting...");

    //txt.Text = sql.testConnectionWithResult();
    if (sql.testConnection())
    {
        txt.Text = "Connected";
        load();
    }
    else
        txt.Text = "SQL Connection error";
}
Snostorp
  • 544
  • 1
  • 8
  • 14
arti
  • 645
  • 1
  • 8
  • 27
  • I would recommend looking at ReactiveUI in general, it will help you with this issue, plus it will _force_ you to use MVVM instead of writing logic in button event handlers. – Alexey Zimarev Oct 05 '16 at 07:08

3 Answers3

6

Here your action comes from a button click action, so you don't need to use RunOnUiThread because you are ready working on this one.

If I understand correctly your code it should look like this :

 private void Btn_Click(object sender, System.EventArgs e)
{
    txt.Text = "Connecting...";

    //do your sql call in a new task
    Task.Run(() => { 
        if (sql.testConnection())
        {
            //text is part of the UI, so you need to run this code in the UI thread
            RunOnUiThread((() => txt.Text = "Connected"; );

            load();
        }   
        else{
            //text is part of the UI, so you need to run this code in the UI thread
            RunOnUiThread((() => txt.Text = "SQL Connection error"; );
        }
    }); 

}

The code inside Task.Run will be called asynchronously without blocking the ui. You can use await word inside the Task.Run if you need to wait for specific work before update UI elements.

OrcusZ
  • 3,555
  • 2
  • 31
  • 48
1

There are many ways to do this, but in the form of your example code:

button.Click += (object sender, System.EventArgs e) =>
{
    Task.Run(async () =>
    {
        RunOnUiThread(() => txt.Text = "Connecting...");
        await Task.Delay(2500); // Simulate SQL Connection time

        if (sql.testConnection())
        {
            RunOnUiThread(() => txt.Text = "Connected...");
            await Task.Delay(2500); // Simulate SQL Load time
            //load();
        }
        else
            RunOnUiThread(() => txt.Text = "SQL Connection error");
    });
};

FYI: There are some great libraries that can help create a reactive user experience, with ReactiveUI being at the top of my list as it also is a MVVM framework...

SushiHangover
  • 73,120
  • 10
  • 106
  • 165
  • why "Task.Run(async () =>"? its not needed cause it gives no benefit with "await". – Gabsch Oct 05 '16 at 07:19
  • But with an async event handler (reactive has to support this, but i dont know) you dont need a new task. Await will just wait there till the Task.Delay returns. – Gabsch Oct 05 '16 at 07:25
  • so this is not possible? btnAccept.Click += (object sender, System.EventArgs e) async () => { await some; }; – Gabsch Oct 05 '16 at 07:34