Fel*_*ani 8 .net c# asynchronous task winforms
我一直在开发一个Windows表单项目,我有10个任务要做,我想在async某种程度上这样做.当用户单击按钮并且我调用async方法执行此操作时,这些任务将会出现.在我的代码中,我已经有了这些进程的参数列表.
我的问题是:
A)如何转换我的代码并行运行所有进程?(我想实现async/await)
B)如何向我的UI应用程序提供反馈?
下面的代码是我试过的:
我的按钮调用方法来启动进程
private void button1_Click(object sender, EventArgs e)
{
// almost 15 process
foreach (var process in Processes)
{
// call a async method to process
ProcessObject(process);
}
}
Run Code Online (Sandbox Code Playgroud)
模拟我的进程获取参数的方法
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我试过这个,但我不确定它是否是更新我的UI(网格)的正确方法.
private void UpdateRow(ProcessViewModel process)
{
dataGridView1.Rows[process.Index - 1].Cells[1].Value = process.Progress;
dataGridView1.Refresh();
}
Run Code Online (Sandbox Code Playgroud)
Sco*_*ain 11
Sriram 在他的回答中介绍了如何进行异步/等待,但是我想向您展示另一种使用他的答案作为基础更新UI线程进度的方法.
.NET 4.5添加了IProgress<T>接口和Progress<T>类.内置的Progress类捕获同步上下文,就像async/await一样,然后当你去报告你的进度时,它会使用该上下文来进行回调(在你的情况下是UI线程).
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);
});
}
Run Code Online (Sandbox Code Playgroud)
首先,对方法说" 不"async void(事件处理程序是例外),因为它内部抛出的异常不会被注意到.而是使用async Task并等待它.
private async void button1_Click(object sender, EventArgs e)// <--Note the async modifier
{
// almost 15 process
foreach (var process in Processes)
{
// call a async method to process
await ProcessObject(process);
}
}
private async Task ProcessObject(ProcessViewModel process)// <--Note the return type
{
// my code is here with some loops
await Task.Run(()=>
{
//Will be run in ThreadPool thread
//Do whatever cpu bound work here
});
//At this point code runs in UI thread
process.Progress++;
// feedback to UI
UpdateRow(process);
}
Run Code Online (Sandbox Code Playgroud)
但是,这将一次只启动一个任务,一旦完成,它将在下一个启动.如果你想立即启动所有这些,你可以启动它们并Task.WhenAll用来等待它.
private async void button1_Click(object sender, EventArgs e)// <--Note the async modifier
{
var tasks = Processes.Select(ProcessObject).ToList();
await Task.WhenAll(tasks);
}
Run Code Online (Sandbox Code Playgroud)