我有这个漫长的过程,我希望在主应用程序表单上显示一个表单,说明它与无处不在的循环进度条一起运行。我只是无法正常工作。表单未正确显示或为进度圆设置动画。如果我尝试使用不同的方法,则任务无法完成!
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();
}
}
答案 0 :(得分:4)
Application.DoEvents()
经常被滥用。除了通过UI重新编写代码的常见问题之外,您还要执行busy-waiting loop。
您没有指定要在何处显示模式对话框。据我了解,代码可能如下所示:
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
添加一些异常处理,取消和进度报告逻辑。以下是关于如何做到这一点的非常好的阅读:Enabling Progress and Cancellation in Async APIs。
我最近也回答了a similar question。看看你是否可以使用相同的方法。
答案 1 :(得分:3)
您似乎没有利用TPL
实际提供的内容。
以下代码段仍会阻止GUI线程:
Task t = new Task(() => ProcessSusan());
while (!t.IsCompleted)
{
Application.DoEvents();
}
因为它会如此迅速地循环,结果将是不合需要的。将其替换为以下内容:
await Task.Run(()=>ProcessSusan());
这会将进程放在不同的线程上,然后在ProcessSusan()
完成后在GUI线程上调用方法的后半部分。
注意强>
您必须是方法定义中async
之后的private
关键字。