How to update UI (text fields) during long running function?

佐手、 提交于 2021-02-18 17:38:07

问题


I know that the question may not make sense, and I'm having a tough time trying to think of a way to explain it, so I will show a snippet of code to help. I'm using Winforms on visual studio express 2010:

private void button1(object sender, EventArgs e)
    {
        txtOutput.Text += "Auto-collecting variables. This may take several minutes";
        string v = foo();
        txtOutput.Text += "\n" + v;
        string b = bar();
        txtOutput.Text += "\n" + b;

        txtOutput.SelectionStart = txtOutput.Text.Length;
        txtOutput.ScrollToCaret(); //scrolls to the bottom of textbox
    }

So basically, when the user clicks button1, I want "Auto-collecting variables..." to be displayed in the textbox, and then have foo() execute, display that, and then have bar() execute, and then display that.

What is currently happening is that foo() and bar() execute, and then everything is displayed all at once after foo() and bar() have executed (functions that take several minutes). Is there anyway to fix this, or is there a work around?

Edit: Version of C# is 4.0. If I update to 4.5 or 5.0, will computers without .NET 4.5/5.0 be able to run the .exe?


回答1:


C# 5.0 makes doing this trivial.

Execute the long running tasks in a background thread using Task.Run and use await to execute the rest of the method as a continuation in the UI thread without blocking the UI thread for the duration of the asynchronous task.

private async void button1(object sender, EventArgs e)
{
    txtOutput.Text += "Auto-collecting variables. This may take several minutes";
    string v = await Task.Run(() => foo());
    txtOutput.Text += "\n" + v;
    string b = await Task.Run(() => bar());
    txtOutput.Text += "\n" + b;

    txtOutput.SelectionStart = txtOutput.Text.Length;
    txtOutput.ScrollToCaret(); //scrolls to the bottom of textbox
}

You can do the same in C# 4.0 like so: (The first solution will be transformed by the compiler into something similar.)

private  void button1(object sender, EventArgs e)
{
    txtOutput.Text += "Auto-collecting variables. This may take several minutes";
    Task.Factory.StartNew(() => foo())
        .ContinueWith(t => txtOutput.Text += "\n" + t.Result
            , TaskScheduler.FromCurrentSynchronizationContext())
        .ContinueWith(t => bar())
        .ContinueWith(t =>
        {
            txtOutput.Text += "\n" + t.Result;
            txtOutput.SelectionStart = txtOutput.Text.Length;
            txtOutput.ScrollToCaret(); //scrolls to the bottom of textbox
        }
            , TaskScheduler.FromCurrentSynchronizationContext());
}



回答2:


Use the BackgroundWorker class to do your processing without blocking UI updates. It has events that can be used to transfer progress information to the UI thread.




回答3:


Depending on the version of .NET, you can use BackgroundWorker (Pre 4.0) or Tasks (Post 4.0 - 3.5 with an add-on)...to name a few.

Backgroundworker Pseudocode:

var backgroundWorker = new BackgroundWorker()

method
{
    //Update UI
    backgroundWorker.RunWorkAsync()
}

asyncworkmethod
{
    //do main logic
}

asynccompletemethod
{
    //Update UI to say done
}

Task Pseudocode:

method
{
     //Update UI
     TaskFactory.StartNew(()=>DoWork).ContinueWith((previousTask)=>UpdateUIToSayDone)
}

And, if you are using 4.5, then you can use the async/await keyword, however that is just syntactic sugar around tasks (mostly...). Servy already has a decent example of this, though if you go that approach




回答4:


Using a background process (read the other answers) is the correct way to go but if you are looking at a very quick workaround you can call Application.DoEvents() after updating the TextBox. In most cases this call will result in your form updating to reflect the changes you made.




回答5:


txtOutput.Update() should do what you want, but you should consider using background thread to complete long running task without blocking UI thread.



来源:https://stackoverflow.com/questions/17069489/how-to-update-ui-text-fields-during-long-running-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!