Luntri
Luntri

Reputation: 620

Asynchronous UI updates in winforms

I'd like to achieve similar effect in textbox in windows forms as you have in the output window in visual studio - that means while it's printing some stuff, you can actually scroll down up and down freely.

Unfortunatelly my attempts with async / await continue to be unsuccessfull (I'm blocking the UI ).

So far I got this :

private async void button1_Click(object sender, EventArgs e)
    {
        try
        {
            richTextBox1.Text = "";
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                await ProcessFile(openFileDialog1.FileNames.First());
            }
        }
        catch (Exception gg)
        {
            SupportingClass.SaveError(gg);
        }
    }
//simplified
private async Task ProcessFilecsv(string path)
{
     IEnumerable<T> products = GetProducts<T>(path);
     foreach (var item in products)
     {
         string select = @"select something from datatable";
         List<object[]> result = await  Support.Overall.RetrieveSelectDataAsync(select);

         richTextBox1.AppendText(int.Parse(result[0][0].ToString()) > 0 ? "Added" : "Not found"));
     }
}

I also tried to use Task.Factory.StartNew(()=> dosth().ContinureWith(x => /* appending to richboxtext1 */ ) but also without success.

What am I missing?

Upvotes: 0

Views: 3074

Answers (1)

stefankmitph
stefankmitph

Reputation: 3306

I think this should do:

private async void button1_Click(object sender, EventArgs e)
{
    ...
    await ProcessFile(openFileDialog1.FileNames.First());
    ...
}

private async Task ProcessFile(string path) 
{
    return Task.StartNew(() => { 
        IEnumerable<T> products = GetProducts<T>(path);
        foreach (var item in products)
        {
            string select = @"select something from datatable";
            List<object[]> result = await  Support.Overall.RetrieveSelectDataAsync(select);

            // i'm using a little helper method here...
            Do(richTextBox1, rb => rb.AppendText(int.Parse...);
        }
    });
}

public static void Do<TControl>(TControl control, Action<TControl> action) where TControl : Control
{
    if (control.InvokeRequired)
    {
        control.Invoke(action, control);
    }
    else
    {
        action(control);
    }
}

Upvotes: 1

Related Questions