OnClick代码在后台执行时禁用Winforms按钮

时间:2014-02-05 19:08:19

标签: c# wpf user-interface

我的“button_click”操作中有一些代码。我希望在此代码工作期间禁用该按钮。

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

但这不起作用。按钮永远不会禁用。

3 个答案:

答案 0 :(得分:3)

您需要在后台线程上运行“some code”部分:

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

答案 1 :(得分: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;
}

答案 2 :(得分: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;