2014-02-05 23 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

相關問題