2012-01-05 30 views
9

Bir winform uygulaması (bir form) var, bu formda bir RichTextBox var. Bu formun yapıcısında, MyClass sınıfının bir örneğini oluşturuyorum. “Form_Load” içinde, MyClass örneğinden Initialisation yöntemini arıyorum. Initialisation yöntemde Form_LoadBackgroundWorker - Çapraz iş parçacığı geçerli değil

myClass.Initialisation(); 

, form kurucu

myClass = new MyClass(RichTextBox richTextBox); 

olarak

, bir döngü içinde, bazı Parmeters diğer maddeleri yapmak okuyun. Uygulamayı dondurmamak için (bazı işlemler biraz zaman alabilir, bir kaç saniye), ben bir BackgroundWorker kullanıyorum. Bunu böyle kullanıyorum (aşağıdaki kod). Ben çalıştırdığınızda

, bu hatayı alıyorum: Çapraz iplik operasyon değil geçerlidir: Denetim ‘richTextBox’ o oluşturulmuş parçacığı dışında başka bir iş parçacığı erişilebilir.

Bunu nasıl çözdüğümü söyleyebilir misiniz? öyle ki sadece UI iş parçacığı olarak UI bileşenlerini erişebilir - Normal parçacığı kurallarının vergisi yerine geçmez BackgroundWorker kullanma richTextBox

public Class MyClass 
{ 
    static BackgroundWorker _bw; 
    public MyClass() 
    { 
     _bw = new BackgroundWorker 
     { 
      WorkerReportsProgress = true, 
      WorkerSupportsCancellation = true 
     }; 
     _bw.DoWork += bw_DoWork; 
     _bw.ProgressChanged += bw_ProgressChanged; 
     _bw.RunWorkerCompleted += bw_RunWorkerCompleted; 
    } 
    static void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     foreach (....) 
     { 
      if (....) 
      { 
       richtextBox.Text.AppendText("MyText"); 
      } 
     } 
     e.Result = true; 
    } 
    static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){} 
    static void bw_ProgressChanged(object sender, ProgressChangedEventArgs e){} 
} 

cevap

29

erişmek olmadığında mükemmel çalışır.

size sadece diğer durumlarda olduğu gibi Control.Invoke/Control.BeginInvoke kullanmak gerekir (UI iş parçacığı üzerinde yetiştirilir) ilerleme/tamamlama olayları kullanarak daha BackgroundWorkerdiğerinden UI güncellemek istiyorsanız. Örneğin: i benzer Buna

richtextBox.Text.Add("MyText"); 

Sorunuzun:

if (....) 
{ 
    Action action =() => richtextBox.Text.Add("MyText"); 
    richtextBox.Invoke(action); // Or use BeginInvoke 
} 
11

bu kodu deneyin

BeginInvoke((MethodInvoker)delegate 
{ 
    richtextBox.Text.Add("MyText"); 
}); 
+0

Bu çalışma, teşekkürler – mili

3

BackgroundWorker bileşenini kullanarak, yalnızca ProgressChanged ve RunWorkerCompleted olayları, UI denetimleri üzerinde yöntemleri/özellikleri çağırmanıza izin verir (her zaman UI iş parçacığında yapılmalıdır). UI olmayan bir iş parçacığında çalışan kullanıcı arabiriminde DoWork olayında UI güncelleştirirken, bu hatayı alıyorsunuz, isterseniz, DoWork olayında Invoke veya BeginInvoke yöntemlerini kullanarak UI denetimlerini muhtemelen güncelleştirmelisiniz.

0

Ekleme:

e.Result = "MyText"; 

Reklamlara bw_DoWork Ve: In

richTextBox1.AppendText((string)e.Result); 

senin bw_RunWorkerCompleted

(kodunuzu sığacak şekilde Alter)

DÜZENLEME:

o BackgroundWorker 'ın çalışmaları sırasında birçok kez yapmış varsa, ekleyebilirsiniz:

_bw.ReportProgress(0, "MyText"); 

bw_DoWork ve:

richTextBox1.AppendText((string)e.UserState); 

bw_ProgressChanged için.

1

Jon Skeet önerisine dayanarak daha temiz ve yapmak için, ben aynısını yapar bir uzantısı yöntemi yapılmış, sadece this TextBox control veya "this Label control" "this Control control" kullanmak değiştirmek (ve temelde her kumanda kolayca güncellenebilir izin verebilir):

internal static class ExtensionMethods 
{ 
    /// <summary> 
    /// Updates the label text while being used in a multithread app. 
    /// </summary> 
    /// <param name="control">The control.</param> 
    /// <param name="text">The text.</param> 
    internal static void UpdateThreadedText(this Label control, string text) 
    { 
     Action action =() => control.Text = text; 
     control.Invoke(action); 
    } 

    /// <summary> 
    /// Refreshes the threaded. 
    /// </summary> 
    /// <param name="control">The control.</param> 
    internal static void RefreshThreaded(this Label control) 
    { 
     Action action = control.Refresh; 
     control.Invoke(action); 
    } 
} 

ve sonra kullanımı oldukça basittir:

this.yourLabelName.UpdateThreadedText("This is the text"); 
this.yourTextBoxName.UpdateThreadedText("This is the text"); 
this.yourControlName.UpdateThreadedText("This is the text"); 

veya

this.yourLabelName.RefreshThreaded(); 

Benim için iyi çalışıyor :)

0

Ayrıca bunu deneyebilirsiniz.

this.Invoke(new MethodInvoker(delegate() 
{ 
    richtextBox.Text.Add("MyText"); 
})); 
İlgili konular