繁体   English   中英

使用对话框执行长任务

[英]Long running task with dialog

我有一个长期运行的过程,我想在主应用程序表单上显示一个表单,解释该表单可以在无处不在的圆圈进度条上运行很长时间。 我什么都无法正常工作。 表单未正确显示或为进度圆设置动画。 如果我尝试使用如图所示的其他方法,则该任务无法完成!

private void lbMethods_SelectedIndexChanged(object sender, EventArgs e)
    {
        switch (lbMethods.SelectedIndex)
        {
            case (int)Methods.none:
                break;
            case (int)Methods.Susan:
                Log("Starting Susan Edge Detection");
                Progressing("Please wait for edge detection");
                Task t = new Task(() => ProcessSusan());
                while (!t.IsCompleted)
                {
                    Application.DoEvents();
                }
                Log("Detection Finished");
                Progressing("", false);
                break;
            default:
                break;
        }
    }

    private void ProcessSusan()
    {
        Susan s = new Susan(CurrentImage);
        List<IntPoint> corners = s.GetCorners();
    }

    private void Progressing(string message, bool Show = true)
    {

        if (Show)
        {
            lblStatus.Text = message;
            Progress.Style = ProgressBarStyle.Continuous;
        }
        else
        {
            lblStatus.Text = "...";
            Progress.Style = ProgressBarStyle.Blocks;
        }
    }

长时间运行的表单代码如下所示:

public partial class FrmProcessing : Form
{
    public string description { get; set; }

    public FrmProcessing(string description)
    {
        InitializeComponent();
        lblDescription.Text = description;

    }

    // Let the calling method close this form.
    public void Close()
    {

        this.Close();
    }


}

Application.DoEvents()通常被滥用。 除了通过UI进行代码重入的常见问题之外,您还在执行忙等待循环

您没有指定要在何处显示模式对话框。 据我了解,代码可能如下所示:

private void lbMethods_SelectedIndexChanged(object sender, EventArgs e)
{
    switch (lbMethods.SelectedIndex)
    {
        case (int)Methods.none:
            break;
        case (int)Methods.Susan:
            Log("Starting Susan Edge Detection");
            Progressing("Please wait for edge detection");

            var dialog = new FrmProcessing();
            dialog.StartTaskFunc = () =>
                Task.Run(ProcessSusan);
            dialog.ShowDialog();

            Log("Detection Finished");
            Progressing("", false);
            break;
        default:
            break;
    }
}

public partial class FrmProcessing : Form
{
    public Func<Task> StartTaskFunc { get; set; }

    public string description { get; set; }

    public FrmProcessing(string description)
    {
        InitializeComponent();
        lblDescription.Text = description;

        // async event handler for "Form.Load"
        this.Load += async (s, e) =>
        {
            // start the task and await it
            await StartTaskFunc();
            // close the modal form when the task finished
            this.Close();
        };
    }
}

这只是一个骨架实现。 您应该为ProcessSusan添加一些异常处理,取消和进度报告逻辑。 以下是有关如何执行此操作的非常好的读取: 在异步API中启用进度和取消

我最近也回答了类似的问题 看看你是否可以使用相同的方法。

看来你没有利用TPL实际提供的东西。

以下代码段仍然阻止GUI线程:

Task t = new Task(() => ProcessSusan());
while (!t.IsCompleted)
{
  Application.DoEvents();
}

因为它将如此迅速地循环,所以结果将是不希望的。 将其替换为以下内容:

await Task.Run(()=>ProcessSusan());

这将把进程放在不同的线程上,然后在ProcessSusan()完成后在GUI线程上调用方法的后半部分。

注意

您必须在方法定义中的private后面输入async关键字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM