2014-01-27 97 views
1

我正在創建一個使用TextBox和ProgressBar的程序,並且每次文本在TextBox或ProgressBar中更改時都會執行GUI凍結的步驟,直到操作完成。當文本和進度條更改時GUI凍結

我知道我需要在不同的線程上運行它們,但是我搜索了整個網絡,但沒有找到適用於我的方法。

這是一個例子,當我寫一個文件,我需要得到它的進展情況:

for (int l = 0; l < newfile.Length; l++) 
{ 
    vfswriter.Write(newfile[l]); 
    double percentage = ((double)l/(double)newfile.Length * 100); 
    this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); 
} 

,當我改變這是一個示例文本:

this.richTextBox1.Text = "Installing patch : "; 

任何幫助將不勝感激。

+1

我沒有看到企圖利用一個BackgroundWorker。這可能有幫助。 –

+0

我試過了,但是我的代碼是這樣的:我調用一個方法,並在它使用文本和背景工作的方法中 – Meydan

+0

正如一個方面說明 - 你可能會失去'百分比'變量,並將進度條更新編碼爲'this。 progressBar1.Value = l * 100/newfile.Length;'。整數數學可以做你想做的事情。 – Enigmativity

回答

3

使用BackgroundWorker,把你的for循環DoWork方法裏面:

backgroundWorker1.DoWork += doWork; 

private void doWork(object sender, DoWorkEventArgs e) 
{ 
    for (int l = 0; l < newfile.Length; l++) 
    { 
     vfswriter.Write(newfile[l]); 
     double percentage = ((double)l/(double)newfile.Length * 100); 
     this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); 
    } 
} 

當您要執行你的循環調用backgroundWorker1.RunWorkerAsync()方法。

您也可以使用ProgressChanged事件來更新你的進度條:

backgroundWorker1.DoWork += doWork; 
backgroundWorker1.ProgressChanged += progressChanged; 

private void doWork(object sender, DoWorkEventArgs e) 
{ 
    for (int l = 0; l < newfile.Length; l++) 
    { 
     vfswriter.Write(newfile[l]); 
     double percentage = ((double)l/(double)newfile.Length * 100); 
     var value = int.Parse(Math.Truncate(percentage).ToString()); 
     backgroundWorker1.ReportProgress(value); 
    } 
} 

private void progressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    this.progressBar1.Value = e.ProgressPercentage; 
} 

更新:如果你想傳遞參數給DoWork方法,你可以做到這一點,當你調用backgroundWorker1.RunWorkerAsync()方法是這樣的:

backgroundWorker1.RunWorkerAsync(argument); 

您可以通過e.ArgumentDoWork方法中訪問它。如果你想傳遞多個參數,你可以用Anonymous Types做的伎倆。例如:

var myArguments = new { Property1 = "some value", Property2 = myId, Property3 = myList }; 
backgroundWorker1.RunWorkerAsync(myArguments); 

在DoWork的方法:

dynamic arguments = e.Argument; 
var arg1 = arguments.Property1; 
var arg2 = arguments.Property2; 
// and so on... 
+0

您未使用ReportProgress。您正在從後臺線程更新GUI。 – LarsTech

+0

@LarsTech現在我添加了:-) –

+0

我怎樣才能將參數傳遞給DoWork? – Meydan

0

您可以使用任務類來創建和運行後臺線程。一個謹慎的詞!任何時候,如果您想從非主線程的線程更新某些內容,則必須使用分派器在主線程上運行代碼。

我的示例代碼:

System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(() => 
{ 
for (int l = 0; l < newfile.Length; l++) 
{ 
    vfswriter.Write(newfile[l]); 
    double percentage = ((double)l/(double)newfile.Length * 100); 
    //This runs the code inside it on the main thread (required for any GUI actions 
    App.Current.Dispatcher.Invoke((Action) (() => 
    { 
    this.progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); 
    } 
} 
}); 
task.Start();