在处理时启用响应式GUI

时间:2016-06-08 10:17:46

标签: c# winforms async-await

当我点击按钮时,我在winform中进行了长时间的处理;即,我正在加载大量文件并进行处理。在处理期间,我的GUI被冻结并且没有响应,这是一个问题,因为处理可能需要10分钟。有没有办法将代码置于某种气泡或其他东西,以便我可以在处理文件时使用GUI?甚至可以添加“取消”按钮。

编辑:René的解决方案正常运行,我也想要progressbar控件:

private async void button1_Click(object sender, EventArgs e)
   {  
       progressBar1.Maximum = ValueWithTOtalNumberOfIterations.Length;
       IProgress<int> progress = new Progress<int>(value => { progressBar1.Value = value;});

       await Task.Run(() =>
       {
           var tempCount = 0;

       //long processing here
       //after each iteration:

           if (progress != null)
           {
               progress.Report((tempCount));
           }
           tempCount++;        
        }            
   }

1 个答案:

答案 0 :(得分:2)

您只需创建按钮的点击处理程序async,然后为长时间运行操作启动Task

public async void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false; // disable button to not get called twice

    await Task.Run(() =>
    {
        // process your files
    }

    button1.Enabled = true; // re-enable button
}

编译器将其转换为状态机。控制流将返回到await关键字的调用者(UI)。当Task完成后,将恢复执行此方法。

要使用“取消” - 按钮,您可以使用TaskCancellationSource或只是定义在处理文件时检查的标志,如果设置了标志则返回(通过您的点击处理程序返回) “取消”按钮):

private bool _stop = false;

private void cancelButton_Click(object sender, EventArgs e)
{
    _stop = true;
}
private async void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false; // disable button to not get called twice

    _stop = false;

    await Task.Run(() =>
    {
        // process your files
        foreach(var file in files)
        { 
            if (_stop) return;
            // process file
        }
    }

    button1.Enabled = true; // re-enable button
}