2012-07-25 64 views
1

我有一个模式对话框,只有当用户单击按钮时弹出一个取消按钮。 Aftre模式对话框弹出后,我想开始一个监视外部事件的漫长过程。如果事件发生,那么对话框将自动关闭。用户可以通过点击取消按钮取消监控过程。在模态对话框弹出后启动长进程

我分配过程开始到显示的事件

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事件,但没有任何更改。 有什么方法可以显示对话框,然后启动该过程?

谢谢

+4

对长时间运行的任务使用BackgroundWorker。 – LarsTech 2012-07-25 14:48:58

回答

4

你的问题是,你正在做的一切在UI线程。您需要将状态监视循环放在单独的线程中,以便UI线程可以保持响应。

有几种方法可以做到这一点,但最简单的地方开始是与BackgroundWorker class

1

使用Task做你LongRunning事件:

CancellationTokenSource _cancelationTokenSource = new CancellationTokenSource(); 
new Task(() => 
{ 
    //Do LongRunning task 
}, _cancelationTokenSource.Token, TaskCreationOptions.LongRunning).Start(); 

使用_cancelationTokenSource取消任务需要的时候。

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

注:文章说,你可以使用InvokeRequired检查关闭,这将被认为是不好的做法crossthreadexception,而不是处理它的正确方法,然后调用Windows窗体上的方法。

1

其他人建议使用BackgroundWorker或其他类型的后台线程。虽然在许多情况下这是适当的,但可能有更好的解决方案。你不只是在做一些长时间运行的任务,你还在等待一些事情发生。而不是不断地投票......不管它是什么,你都应该使用事件。应该有一个事件在您完成时触发,并且您应该订阅该事件,以便在满足正确条件时执行您需要执行的任何操作(即关闭对话框)。

+0

谢谢,这是绝对正确的,但我可以将事件处理程序分配给BackgroundWorker类,以在处理完成时执行某些操作。 – HamoriZ 2012-07-25 15:20:08

+0

@ZoltanHamori根据实现的不同,可能会在UI或非UI线程中触发事件处理程序。很可能它将是一个非UI线程。如果它不是你想要的那个,你总是可以得到另一个。如果您处于非UI线程中,则可以编组到UI线程中,如果您处于UI线程中,则可以启动一个新任务以在后台运行。 – Servy 2012-07-25 15:24:18