2011-06-26 14 views
37

Bunun 3 yöntemi olduğunu biliyorum. Programımda bir mesaj göndermek için bir yöntem var. Genellikle geç kalır ve program bazen bir tuşa basma mesajını hiç göndermez. Zaman zaman beklediğimden 5 saniye kadar geç ve program donuyor. İletiyi beklendiği gibi göndermek ve programın her zaman normal şekilde çalışmasına izin vermek için BackgroundWorker kullanmak istiyorum. İletiyi bir düğme işleyicisine göndermek için kodum vardı. Şimdi bu eşdeğer kodu nereye koyacağım? Tüm bunların hala bir düğmeye basılarak ele alınmasını istiyorum.BackgroundWorker nasıl kullanılır?

Bu uygun işleyici mi?

backgroundWorker1.RunWorkerAsync(); 

ve :

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {} 

Ben düğme işleyicisi içinde kodumu koyacağım? Ve bundan önce: ProgressBar olduğu

carga.progressBar1.Minimum = 0; 
carga.progressBar1.Maximum = 100; 

Carga benim diğer şeklidir. Bu senaryoda bir BackgroundWorker'ı nasıl kullanırım?

cevap

57

İlerleme çubuğunu yalnızca UI iş parçacığıyla eşitlendikleri için ProgressChanged veya RunWorkerCompleted olay işleyicilerinden güncelleyebilirsiniz.

Temel fikir şöyledir. Thread.Sleep sadece bazı çalışmaları burada simüle ediyor. Gerçek yönlendirme aramanızla değiştirin.

public Form1() 
{ 
    InitializeComponent(); 

    backgroundWorker1.DoWork += backgroundWorker1_DoWork; 
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; 
    backgroundWorker1.WorkerReportsProgress = true; 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    backgroundWorker1.RunWorkerAsync(); 
} 

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     Thread.Sleep(1000); 
     backgroundWorker1.ReportProgress(i); 
    } 
} 

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 
+0

Yukarıdaki çözüm Alex Aza tarafından verilen kodun üstüne eklemek için örnek gidiyorum - nasıl geri ana (UI) için arka plan işçi dönen veri almak do ipliği? –

+0

Tek, UI (WPF ilerleme çubuğu) ProgressChanged yönteminden güncelleştirme hakkında bir özel durum var. Ayrıca, https://stackoverflow.com/questions/9732709/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it/43455920 benimkine benzer bir sorunu var gibi görünüyor, ve Application.Current.Dispatcher.Invoke() 'için gerekliliğini belirtmektedir. Bunun hakkında bir fikrin var mı? –

34

Bu biraz eski olduğunu biliyorum ama durumda başka acemi, ben burada, temel işlemleri biraz daha kapsar bazı kodlar paylaşacağım bu geçiyor da seçeneği içerir başka bir örnektir İşlemi iptal etmek ve ayrıca kullanıcıya sürecin durumunu bildirmek. I) (senin Button1_click olarak

public Form1() 
{ 
    InitializeComponent(); 

    backgroundWorker1.DoWork += backgroundWorker1_DoWork; 
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; 
    backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted; //Tell the user how the process went 
    backgroundWorker1.WorkerReportsProgress = true; 
    backgroundWorker1.WorkerSupportsCancellation = true; //Allow for the process to be cancelled 
} 

//Start Process 
private void button1_Click(object sender, EventArgs e) 
{ 
    backgroundWorker1.RunWorkerAsync(); 
} 

//Cancel Process 
private void button2_Click(object sender, EventArgs e) 
{ 
    //Check if background worker is doing anything and send a cancellation if it is 
    if (backgroundWorker1.IsBusy) 
    { 
     backgroundWorker1.CancelAsync(); 
    } 

} 

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     Thread.Sleep(1000); 
     backgroundWorker1.ReportProgress(i); 

     //Check if there is a request to cancel the process 
     if (backgroundWorker1.CancellationPending) 
     { 
      e.Cancel = true; 
      backgroundWorker1.ReportProgress(0); 
      return; 
     } 
    } 
    //If the process exits the loop, ensure that progress is set to 100% 
    //Remember in the loop we set i < 100 so in theory the process will complete at 99% 
    backgroundWorker1.ReportProgress(100); 
} 

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 

private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
{ 
    if (e.Cancelled) 
    { 
     lblStatus.Text = "Process was cancelled"; 
    } 
    else if (e.Error != null) 
    { 
     lblStatus.Text = "There was an error running the process. The thread aborted"; 
    } 
    else 
    { 
     lblStatus.Text = "Process was completed"; 
    } 
} 
İlgili konular