Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - Cross Thread Error using Async and Await on TextBox

I am new to Async and Await and have created a simple project in order to understand how it works. For this, I have a simple Windows Form application that has 2 elements:

  • Get Completed Items button
  • TextBox showing all Completed Items retrieved

When I click the button, it should display all completed Items in the TextBox. This is the code I have written:

private async void btnGetCompletedItems_Click(object sender, EventArgs e)
{
    QueueSystem queueSystem = QueueSystem.NewInstance(75);

    Stopwatch watch = new Stopwatch();

    watch.Start();
    await Task.Run(() => GetCompletedItems(queueSystem));
    watch.Stop();

    lblTime.Text = $"{watch.ElapsedMilliseconds.ToString()} ms";

}

private void GetCompletedItems(QueueSystem queueSystem)
{
    foreach (var item in queueSystem.GetCompletedItems())
    {
        txtItems.Text += $"{txtItems.Text}{item.ItemKey}{Environment.NewLine}";
    }
}

However, I am getting an error in

txtItems.Text += $"{txtItems.Text}{item.ItemKey}{Environment.NewLine}";

The error says

Additional information: Cross-thread operation not valid: Control 'txtItems' accessed from a thread other than the thread it was created on.

I checked in Debug and a new thread was created for GetCompletedItems(). When I read about Async and Await, I read that it doesn't necessarily create a new thread but it seems to have created a new one for some reason.

Is my implementation and understanding of Async and Await wrong? Is it possible to use Async and Await in a Windows Forms application?

like image 787
thecodeexplorer Avatar asked Nov 23 '18 03:11

thecodeexplorer


Video Answer


1 Answers

You cannot access UI thread on a different thread. This should help

private async void btnGetCompletedItems_Click(object sender, EventArgs e)
{
    QueueSystem queueSystem = QueueSystem.NewInstance(75);

    Stopwatch watch = new Stopwatch();

    watch.Start();
    var results = await Task.Run(() => queueSystem.GetCompletedItems());
    foreach (var item in results)
    {
        txtItems.Text += $"{txtItems.Text}{item.ItemKey}{Environment.NewLine}";
    }
    watch.Stop();

    lblTime.Text = $"{watch.ElapsedMilliseconds.ToString()} ms";

}
like image 200
Elwick Avatar answered Sep 22 '22 11:09

Elwick