0

I'm new to C# and I'm trying to use async and await function in C# to work with threading and non blocking GUI.

This is what I have so far:

 public async Task ReadInfo()
        {
            string serial;
            android.UpdateDeviceList();
            if (android.HasConnectedDevices)
            {
                serial = android.ConnectedDevices[0];
                device = android.GetConnectedDevice(serial);
                string model = device.BuildProp.GetProp("ro.product.model");
                string bootloader = device.BuildProp.GetProp("ro.bootloader");
                string pda = device.BuildProp.GetProp("ro.build.PDA");

                addlog("Model : " , Color.White, true, true);
                addlog(model, Color.DodgerBlue, true, false); 
                addlog("Bootloader : ", Color.White, true, true);
                addlog(bootloader, Color.DodgerBlue, true, false); 
                addlog("PDA Version : ", Color.White, true, true);
                addlog(pda, Color.DodgerBlue, true, false); 
            }
            else
            {
                addlog("ADB device not found.", Color.Red, true, true);
            }

        }

This is the AddLog Method:

public void addlog(string s, Color color, bool isBold, bool newline = false)
        {
            if (newline)
            {
                rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.AppendText("\r\n")));
            }
            Color selectionColor = color;
            rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionStart = rtbLog.Text.Length));
            rtbLog.BeginInvoke(new MethodInvoker(() => selectionColor = rtbLog.SelectionColor));
            rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionColor = color));
            if (isBold)
            {
                rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionFont = new Font(rtbLog.Font, FontStyle.Bold)));
            }
            rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.AppendText(s)));
            rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionColor = selectionColor));
            rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionFont = new Font(rtbLog.Font, FontStyle.Regular)));
            rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.ScrollToCaret()));
        }

On Button1_Click I have this:

 private async void Button1_Click(object sender, EventArgs e)
        {
           await  ReadInfo();
        }

I don't know why its freezing the GUI.

Solution to the problem

Changing

public async Task ReadInfo()

to

 public void ReadInfo()

and calling on button1_click as

Task.Run(() => ReadInfo());
Aman Ali
  • 51
  • 8
  • Using `async` and `await` does not magically create new threads for you. Also, since `ReadInfo` does not have a single `await` on it, the entire method runs synchronously. I would suggest you to get started with the official documentation: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ – Camilo Terevinto Jun 02 '18 at 23:23
  • What is `rtbLog` and why are you doing `BeginInvoke` with `MethodInvoker` just to set properties on it? – Matt Johnson-Pint Jun 02 '18 at 23:27
  • Cross Thread Calls. – Aman Ali Jun 02 '18 at 23:29
  • I would suggest you to make `ReadInfo` `public void ReadInfo` and change your button click to `await Task.Run(() => ReadInfo());`. That should take care of not freezing the GUI and keeping your code clean – Camilo Terevinto Jun 02 '18 at 23:50
  • @CamiloTerevinto Thank you for making it short and easy that's what i expect as an answer – Aman Ali Jun 03 '18 at 00:02

1 Answers1

4

Nothing in ReadInfo is actually asynchronous - in fact, the compiler should already be warning you about this. If there is no asynchronous incomplete await, everything continues on the current thread - the UI thread.

Adding async does not make code run on a different thread.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    @CamiloTerevinto even `await` doesn't explicitly add any threading. In cases like this, I would expect sync-context to apply, so `await` is a call back to the UI thread *anyway* – Marc Gravell Jun 02 '18 at 23:26
  • How to implement new thread in this scenario ? – Aman Ali Jun 02 '18 at 23:26
  • @AmanAli if you want to use a thread: *use a thread* - any of `Thread`, `ThreadPool.QueueUserWorkItem` or `Task.Run` should be good candidates – Marc Gravell Jun 02 '18 at 23:27
  • Yeah, I know. But it is awesome how people do not read the warning that the method will run synchronously. – Camilo Terevinto Jun 02 '18 at 23:27
  • I don't see any warning. – Aman Ali Jun 02 '18 at 23:28
  • @AmanAli you should see CS1998 "This async method lacks 'await' operators and will run synchronously.". If you aren't seeing that, you've probably toggled the warnings away. To show them, click the yellow triangle in the "Error List" pane, like here: https://i.stack.imgur.com/RLHje.png – Marc Gravell Jun 04 '18 at 07:13