2015-07-10 249 views
0

我想在帶有滾動樣式的窗體上添加一個ProgressBar,以顯示用戶正在進行的操作。在耗時的操作過程中,表單不會更新,因此ProgressBar也會「凍結」。C# - 帶滾動條樣式的ProgressBar

我已經檢查了幾篇關於BackgroundWorker的帖子,但在我的案例中操作不報告進度,這就是爲什麼我需要一個Marquee欄。

讚賞任何幫助或代碼片段。

注:我需要使用.NET 4.0(對XP的支持),所以我不能使用Task.Run :(

button1_Click(object sender, EventArgs e) 
{ 
    progressBar1.Style = ProgressBarStyle.Marquee; 
    progressBar1.MarqueeAnimationSpeed = 50; 

    // INSERT TIME CONSUMING OPERATIONS HERE 
    // THAT DON'T REPORT PROGRESS 
    Thread.Sleep(10000); 

    progressBar1.MarqueeAnimationSpeed = 0; 
    progressBar1.Style = ProgressBarStyle.Blocks; 
    progressBar1.Value = progressBar1.Minimum; 

} 
+0

你知道迭代器的數量在您的消費過程的開始做些什麼呢?在這種情況下,我可能會提出一些實施建議。 – Graffito

+0

這不是一個迭代,更像是等待MySQL連接或LDAP響應。 – dobragab

回答

7

我查了一下BackgroundWorker的幾個職位,但在我的情況下, 操作不報告進度,這就是爲什麼我需要一個跑馬燈吧。

您可以使用BackgroundWorker,只是不要使用它的「進度」部分。這兩件事並不相互排斥......

例子:

private void button1_Click(object sender, EventArgs e) 
    { 
     button1.Enabled = false; 
     progressBar1.Style = ProgressBarStyle.Marquee; 
     progressBar1.MarqueeAnimationSpeed = 50; 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += bw_DoWork; 
     bw.RunWorkerCompleted += bw_RunWorkerCompleted; 
     bw.RunWorkerAsync(); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // INSERT TIME CONSUMING OPERATIONS HERE 
     // THAT DON'T REPORT PROGRESS 
     Thread.Sleep(10000); 
    } 

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     progressBar1.MarqueeAnimationSpeed = 0; 
     progressBar1.Style = ProgressBarStyle.Blocks; 
     progressBar1.Value = progressBar1.Minimum; 

     button1.Enabled = true; 
     MessageBox.Show("Done!"); 
    } 
+0

聽起來不錯!是否有可能從bw_RunWorkerCompleted訪問所有表單控件? (所以它在同一個線程上運行?) button1.Enabled = true; MessageBox.Show(「Done!」); 這表明了這一點。 – dobragab

+0

是的,你可以安全**從RunWorkerCompleted()事件中訪問所有的控件,因爲它已經被BackgroundWorker控件編組到主UI線程。如果將來使用'ProgressChanged()'事件也是如此。 –

0

你仍然需要在不同的線程運行耗時的工作。 ..你是在UI線程,這意味着UI沒有機會做任何UI更新上運行它(因此凍結您見證)!

您應該考慮使用Task<>代替BackgroundWorker

見mor。的https://msdn.microsoft.com/en-us/library/hh195051%28v=vs.110%29.aspx電子信息Task<>


如果您不能使用Task<>,那麼你應該恢復到BackgroundWorker並使用WorkCompleted情況下,停止選取框並移動程序到其下一步的操作。

+0

謝謝,我會看看它。請注意,我無法使用Task.Run,​​正如我在編輯中提到的那樣。是否有任何由.NET 4.0支持的替代方法? – dobragab

0

已解決。不過,我認爲這是處理它的最不優雅的方式。

button1_Click(object sender, EventArgs e) 
{ 
    progressBar1.Style = ProgressBarStyle.Marquee; 
    progressBar1.MarqueeAnimationSpeed = 50; 


    Task task = Task.Factory.StartNew(() => 
    { 
     // INSERT TIME CONSUMING OPERATIONS HERE 
     // THAT DON'T REPORT PROGRESS 
     Thread.Sleep(10000); 
    }); 

    while (!task.IsCompleted) 
    { 
     Application.DoEvents(); 
     Thread.Sleep(1); 
    } 

    progressBar1.MarqueeAnimationSpeed = 0; 
    progressBar1.Style = ProgressBarStyle.Blocks; 
    progressBar1.Value = progressBar1.Minimum; 

} 
+0

這通常是一個**非常糟糕的主意,讓你的點擊處理程序像這樣的輪詢循環。 –