2012-12-04 13 views
10

Kuyruk sınıfından miras alınan bir özel Kuyruk sınıfım var. Bu bir Item Item öğesi var. Bu olayın olay işleyicisinde bir yöntem yürütüyorum. Ama ana iş parçacığı olmak istiyorum, ancak ana iş parçacığı dışında çalışıyor. Bunu nasıl yapacağımı bilmiyorum. Herhangi bir öneri ?Olay işleyicisinden ana iş parçacığı bir yöntem yürütme

//My custom class 


using System; 
using System.Collections; //Required to inherit non-generic Queue class. 

namespace QueueWithEvent 
{ 
    public class SmartQueue:Queue 
    { 

     public delegate void ItemAddedEventHandler(object sender, EventArgs e); 

     public event ItemAddedEventHandler ItemAdded; 

     protected virtual void OnItemAdded(EventArgs e) 
     { 
      if (ItemAdded != null) 
      { 
       ItemAdded(this, e); 
      } 
    } 

    public override void Enqueue(object Item) 
    { 
     base.Enqueue(Item); 
     OnItemAdded(EventArgs.Empty); 
    }   

    } 
} 



//Winform application 

using System; 
using System.ComponentModel; 
using System.Windows.Forms; 
using QueueWithEvent; 

namespace TestApp 
{ 
    public partial class Form1 : Form 
    { 

    SmartQueue qTest = new SmartQueue(); 

    public Form1() 
    { 
     InitializeComponent(); 
     qTest.ItemAdded += new SmartQueue.ItemAddedEventHandler(this.QChanged); 
    } 

    private void btnStartBgw_Click(object sender, EventArgs e) 
    { 
     DisplayThreadName(); 
     bgwTest.RunWorkerAsync(); 
    } 

    private void bgwTest_DoWork(object sender, DoWorkEventArgs e) 
    { 
     try 
     { 
      for (int i = 0; i < 11; i++) 
      { 
       string valueTExt = i.ToString(); 
       qTest.Enqueue(valueTExt); 
       System.Threading.Thread.Sleep(5000); 
      } 
     } 
     catch (Exception Ex) 
     { 
      MessageBox.Show(Ex.Message); 

     } 
    } 


    private void DisplayThreadName() 
    { 
     string tName = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(); 
     txtThreadName.Text = tName;   
    } 

    private void QChanged(object sender, EventArgs e) 
    { 
     //#########I want this method to run on main thread ############# 
     DisplayThreadName(); 
    } 
} 
} 

Şimdiden teşekkürler. SKPaul.

+1

pencere formları veya WPF? – Tigran

cevap

19

Arka plan iş parçacığındaki öğeleri sıraya sokuyorsunuz (DoWork olay işleyicisi arka plan iş parçacığı üzerinde çalışır), böylece etkinliğiniz arka plan iş parçacığında da yükseldi.

UI iş parçacığı üzerinde olup olmadığını doğrulamak için InvokeRequired yöntemini kullanın. Ve eğer değilse o zaman UI iş parçacığı üzerinde kod çalıştırmasına Invoke kullanın: sizin için

private void QChanged(object sender, EventArgs e) 
{ 
    if (InvokeRequired) 
    { 
     Invoke((MethodInvoker)delegate { QChanged(sender, e); }); 
     return; 
    } 
    // this code will run on main (UI) thread 
    DisplayThreadName(); 
} 

Başka bir seçenek - öğeleri kuyruğa sokmak için ProgressChanged olayını kullanmak (true WorkerReportsProgress ayarlamak için unutmayın).

private void bgwTest_DoWork(object sender, DoWorkEventArgs e) 
{ 
    BackgroundWorker worker = (BackgroundWorker)sender; 

    for (int i = 0; i < 11; i++) 
    { 
     // use user state for passing data 
     // which is not reflecting progress percentage 
     worker.ReportProgress(0, i); 
     System.Threading.Thread.Sleep(5000); 
    } 
} 

private void bgwTest_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    string valueTExt = e.UserState.ToString(); 
    qTest.Enqueue(valueTExt); 
} 
+1

Teşekkürler lazyberezovsky, şimdi çalışıyor. Çok teşekkürler. –

+7

Ana sayfanızın bir Formu yoksa ne olur? Örneğin bir tepsi uygulaması için bir ApplicationContext sınıfı. Sonra Invoke mevcut değil. – xr280xr

1

Bunu içeri oluşturulmuş bir konuya operasyonları sevk edebilir sınıfınızda üyesi olarak AsyncOperation birleştiren edilir BackgroundWorker aynı yaklaşımı kullanabilirsiniz: Bu olay işleyicisi UI iş parçacığı üzerinde çalışır

"null" argümanı ile kurucunuzda örnekleyin. Bu, geçerli iş parçacığına "bağlı" bir eşzamansız işlem oluşturur.

public SmartQueue() 
{ 
    AsyncOp = AsyncOperationManager.CreateOperation(null); 
} 

Sonra olay Post için AsyncOp kullanabilirsiniz. SmartQueue örneğini oluşturdu aynı iş parçacığı üzerinde OnItemAdded işleyicileri (abone) çalıştırır

public override void Enqueue(object Item) 
{ 
    base.Enqueue(Item); 
    AsyncOp.Post(OnItemAdded, EventArgs.Empty); 
} 

.

+0

OP WPF kullanmıyor - kod örneğine bakın. –

-1

ana iş parçacığı bu kod ile deneyin:

SmartQueue smartQueue = new SmartQueue(); 

public Form1() 
{ 
    InitializeComponent(); 
    smartQueue.ItemAdded += new SmartQueue.ItemAddedEventHandler(smartQueue_ItemAdded); 
} 

void smartQueue_ItemAdded(object sender, EventArgs e) 
{ 
    // add your code in here 
} 
+0

Bu, OP tarafından zaten yapılmış olan basit etkinlik aboneliğidir. Çoklu iş parçacığı sorununu nasıl çözer? –

+0

Çok iş parçacığı sorunu için, iş parçacığı güvenliğini sağlamak için test etmeden ve çağırmadan önce temsilci için geçici değişken atamanız gerekir. Belki böyle: 'korumalı sanal geçersiz OnItemAdded (EventArgs e) {var temp = Itemlamalı; if (temp! = null) {temp (this, e);}} ' – YD4

+0

Olay işleyicisinin ana iş parçacığı üzerinde çalışmasını nasıl sağlar? –

İlgili konular