2014-02-05 24 views
2

我的“button_click”动作中有一些代码。我想在代码工作期间禁用按钮。当OnClick代码在后台执行时禁用Winforms按钮

private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     button1.IsEnabled = false; 
     // some code (its take about 2-5 sec) 
     button1.IsEnabled = true; 
    } 

但这不起作用。该按钮从不禁用。

回答

3

您需要在后台线程上运行“一些代码”的一部分:

button1.Enabled = false; 
Task.Factory.StartNew(() => { 
    // some code (its take about 2-5 sec) 
}).ContinueWith(task => { 
    button1.Enabled = true; 
}, TaskScheduler.FromCurrentSynchronizationContext()); 
+1

好吧,现在它的工作,但我需要把那里的大块Dispatcher代码,因为我生成了新的组件(如TreeView)。 – Misha

+1

@Misha:你可以尝试从UI部分分离逻辑(如果可能的话可能会延迟创建)。最后,UI线程将会锁定,但尽量减少它。 –

+0

@Misha对,我应该提到,任何与UI相关的东西都必须分派回UI线程。 – McGarnagle

2

这是因为您的UI在整个操作过程中被锁定。

你应该在某种后台线程中写任务。

您可以使用BackgroundWorker,但更好的是Task

BackgroundWorker bgw = new BackgroundWorker(); 
bgw.DoWork += bgw_DoWork; 
bgw.RunWorkerCompleted += bgw_RunWorkerCompleted; 

button.Enabled = false; 

bgw.RunWorkerAsync(); 

private void bgw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // your task 
} 

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // update the button 
    button.Enabled = true; 
} 
+3

需要在调度程序上排队吗?只在UI线程上调用“RunWorkerCompleted”。 –

+0

@RohitVats:谢谢。好点子。 –

1

Dispatcher负责消息在WPF抽。每个线程都有与其关联的调度程序,它负责根据项目的DispatcherPriority排队该线程上的东西。

在你的情况下,GUI渲染是在DispatcherPriority.Render上完成的,但现在调度程序正在忙于执行你的按钮点击事件处理程序代码,因此GUI渲染永远不会发生,直到它完成代码执行。这就是为什么你看到只有当你的处理程序完全执行时刷新按钮。

在阿里纳斯什么McGarnagle提出要去工作,但你可以优先Render这将迫使所有排队的优先级高于或等于渲染的项目做到这一点反过来也通过明确地排队空委托对调度员继续之前被处理进一步。因此,您将在GUI上看到刷新:

button1.IsEnabled = false; 
Application.Current.Dispatcher.Invoke((Action)(() => { }), 
             DispatcherPriority.Render); 
// some code (its take about 2-5 sec) 
button1.IsEnabled = true; 
+1

+1:非常有帮助的解释。 –

+0

这不适合我。 – Misha

相关问题