我有一个带有取消按钮的模态对话框,当用户点击按钮时会弹出该对话框。弹出模态对话框后,我想启动一个监视外部事件的长进程。如果事件发生,则对话框将自动关闭。用户可以通过单击取消按钮取消监视过程。
我将流程开始分配给了已显示的事件
private void ProceedForm_Shown(object sender, System.EventArgs e)
{
controller.StartSwiping();
}
流程本身就是一个循环
public void StartSwiping()
{
Status status;
do
{
status = CallForFeedback();
} while (status == Status.Pending);
form.DialogResult = DialogResult.OK;
form.Close();
}
该过程开始正常,但没有弹出对话框,因此用户无法取消该过程。我也尝试将开始分配给Load事件,但没有任何改变。 有没有办法显示对话框,然后启动该过程?
由于
答案 0 :(得分:4)
您的问题是您正在UI线程中执行所有操作。您需要将状态监视循环放在单独的线程中,以便UI线程可以保持响应。
有几种方法可以做到这一点,但一个简单的起点是BackgroundWorker class
答案 1 :(得分:1)
使用Task
执行LongRunning
个活动:
CancellationTokenSource _cancelationTokenSource = new CancellationTokenSource();
new Task(() =>
{
//Do LongRunning task
}, _cancelationTokenSource.Token, TaskCreationOptions.LongRunning).Start();
使用_cancelationTokenSource
在需要时取消任务。
答案 2 :(得分:1)
当你阻止UI线程时,我会将长时间运行的代码移动到后台线程上,这就是UI永远不会显示的原因。
将后台工作者类用于控制器功能http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
当后台工作者完成工作(即收到事件)后,您可以使用以下机制回调到UI线程:
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
注意:文章说你可以关闭crossthreadexception这会被认为是不好的做法,而是使用InvokeRequired检查以正确的方式处理它,然后在Windows窗体上调用方法。
答案 3 :(得分:1)
其他人建议使用BackgroundWorker或其他类型的后台线程。虽然在许多情况下这是合适的,但可能有更好的解决方案。你不只是在做一些长期运行的任务,而是在等待一些事情发生。而不是不断地轮询......不管它是什么,你应该使用事件。完成后应该会触发一个事件,并且您应该在满足正确条件时订阅该事件以执行您需要执行的操作(即关闭对话框)。