1

I use C# Winforms

I am using Task.Run() in order to get my WinForm does not freeze.

Inside this code, I need to update the textbox text.

I tried to update textbox text directly and through Invoke but non worked.

I tried to minimize my code to just focus on the problem

Any idea how to update the text box inside Task.Run()?

public async void MyFunction()
{
    await Task.Run(() =>
    {
        lvwFiles.BeginInvoke(new Action(() =>
        {
            foreach (ListViewItem item in this.lvwFiles.Items)
            {
                txtLog.Text = item.Text + "\r\n" +txtLog.Text;
                if (txtLog.InvokeRequired)
                {
                    txtLog.Invoke(new MethodInvoker(delegate { txtLog.Text = item.Text + "\r\n" + txtLog.Text; }));
                }
                Thread.Sleep(4000);

                item.BackColor = Color.FromArgb(128, 255, 128);
            }
        }));
    });
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
asmgx
  • 7,328
  • 15
  • 82
  • 143
  • 1
    Does this answer your question? [How do I update the GUI from another thread?](https://stackoverflow.com/questions/661561/how-do-i-update-the-gui-from-another-thread) – Jonathan Barraone Jan 22 '22 at 02:47
  • @JonathanBarraone this is the solution in my answer and does not work! – asmgx Jan 22 '22 at 02:53
  • _”I am using Task.Run() in order to get my WinForm does not freeze”_ … ? … Why would the window freeze if you updated a text box? – JohnG Jan 22 '22 at 02:54
  • @JohnG "I tried to minimize my code to just focus on the problem" the WinForm freezes because it upload files to SFTP – asmgx Jan 22 '22 at 02:55
  • Instead of using the `BeginInvoke` in order to update the UI from inside the `Task.Run` lambda, you could consider updating the UI after the `Task.Run` has completed. The result of the computation can be obtained by just awaiting the `Task.Run`, as shown [here](https://stackoverflow.com/questions/68052346/await-dispatcher-invokeasync-vs-dispatcher-invoke/68053609#68053609). Alternatively you could use a `Progress` to report progress to the UI while the `Task.Run` is running, as shown [here](https://stackoverflow.com/questions/12414601/async-await-vs-backgroundworker/64620920#64620920). – Theodor Zoulias Jan 22 '22 at 03:20

1 Answers1

1

You're using Task.Run to run it in a different thread, but then you're using BeginInvoke, which tells it to run that code on the UI thread. So the result is that your code is run on the UI thread. And since you're using Thread.Sleep(), you lock your UI thread.

Instead, run it all on your UI thread and use Task.Delay() instead of Thread.Sleep() to avoid locking the UI thread.

public async void MyFunction()
{
    foreach (ListViewItem item in this.lvwFiles.Items)
    {
        txtLog.Text = item.Text + "\r\n" + txtLog.Text;
        await Task.Delay(4000);

        item.BackColor = Color.FromArgb(128, 255, 128);
    }
}
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84