Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

c# - How to provide a feedback to UI in a async method?

I have been developing a windows forms project where I have a 10 tasks to do, and I would like to do this in a async way. These tasks will star when the user click in a button and I call a async method to do this. In my code, I already have a list of parameters for these processes.

My questions is:

A) How transform my code to run all process in parallel? (I would like to implement async/await)

B) How to provide a feedback to my UI application?

The code bellow is what I have tried:

My button to call a method to start processes

private void button1_Click(object sender, EventArgs e)
{
    // almost 15 process
    foreach (var process in Processes)
    {
        // call a async method to process
        ProcessObject(process);
    }
}

The method to simulate my process getting a parameter

private async void ProcessObject(ProcessViewModel process)
{
    // this is my loop scope, which I need to run in parallel
    {
       // my code is here

       // increment the progress of this process
       process.Progress++;

       // feedback to UI (accessing the UI controls)
       UpdateRow(process);
    }
}

I tried this, but I am not sure if it is the right way to update my UI (a grid).

private void UpdateRow(ProcessViewModel process)
{
    dataGridView1.Rows[process.Index - 1].Cells[1].Value = process.Progress;
    dataGridView1.Refresh();
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Sriram covered how to do the async/await in his answer, however I wanted to show you another way to update the progress on the UI thread using his answer as a base.

.NET 4.5 added the IProgress<T> interface and the Progress<T> class. The built in Progress class captures the synchronization context, just like async/await does, then when you go to report your progress it uses that context to make its callback (the UI thread in your case).

private async void button1_Click(object sender, EventArgs e)
{
     var progress = new Progress<ProcessViewModel>(UpdateRow); //This makes a callback to UpdateRow when progress is reported.

     var tasks = Processes.Select(process => ProcessObject(process, progress)).ToList();
     await Task.WhenAll(tasks);
}

private async Task ProcessObject(ProcessViewModel process, IProgress<ProcessViewModel> progress)
{
    // my code is here with some loops
    await Task.Run(()=>
    {
        //Will be run in ThreadPool thread
        //Do whatever cpu bound work here


        //Still in the thread pool thread
        process.Progress++;

        // feedback to UI, calls UpdateRow on the UI thread.
        progress.Report(process); 
    });
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...