2010-08-04 8 views
6

Ayırmak için bir saniyeden bir iki saniyeye kadar alabilen bir nesneyim var. Bunun nedeni, kurucunun birkaç kilobayttan birkaç megabayt olabilen bir web servisinden veri alması ve kullanıcının bağlantı hızına bağlı olarak performansının büyük ölçüde değişmesidir. Bu nedenle, ilerleme bildirimini ele alacak olayları koymak istiyorum. İşte Yapıcılarda Etkinlik İşleyicileri - Mümkün veya Bile Akıllı mı?

sorum şu: Ben işleyicileri yapıcı olayı koyabilir miyim ya gerektiği eylem bu tür bir Yük yöntemi ile yapılabilir? Ben her zaman boş olan kurucusuna olay işleyicileri kravat çalıştığınızda Ancak çağrılan

public class MyObject 
{  
public event EventHandler<UpdateLoadProgressEventArgs> UpdateLoadProgress;  

public MyObject(int id) 
{ 
    Background worker bgWorker = new BackgroundWorker(); 
    bgWorker.DoWork += delegate(object s, DoWorkEventArgs args) 
    { 
     //load data and update progress incrementally 
     UpdateLoadProgress(this, new UpadteLoadProgressEventArgs(progressValue)); 

     Result = someValue;   
    } 
    bgWorker.RunWorkAsync(); 

} 

public int Result 
{ 
    get; 
    set; 
} 

} 

: Örneğin

MyObject o = new MyObject(1); 
o.UpdateLoadProgress += new EventHandler<EventArgs>(o_UpdateLoadProgress); 

bu olmuyorsa varsayalım telden dolayı kurucudan sonra olayları yukarı. Gördüğüm tek alternatif, kurucunun çalışmasını yapan bir Load yöntemi oluşturuyor. Dezavantajı, bu sınıfı kullanan herkesin, Sonucu (veya başka bir özelliği) erişmeye çalışmadan önce Yük'ü çağırması gerektiğini bilmesidir.

DÜZENLEME: İşte nihai çözümdür:

MyObjectBuilder Sınıf

public class MyObjectBuilder 
    { 
     public event ProgressChangedEventHandler ProgressChanged; 

     public MyObject CreateMyObject() 
     { 
      MyObject o = new MyObject(); 
      o.Load(ProgressChanged); 

      return o; 
     } 
    } 

MyObject Sınıf

public class MyObject 
    { 
     public int Result { get; set;} 

     public void Load(ProgressChangedEventHandler handler) 
     { 
      BackgroundWorker bgWorker = new BackgroundWorker(); 
      bgWorker.WorkerReportsProgress = true; 
      bgWorker.ProgressChanged += handler; 

      bgWorker.DoWork += delegate(object s, DoWorkEventArgs args) 
      { 
       for (int i = 0; i < 100; i++) 
       { 
        Thread.Sleep(10); 
        Result = i; 

        bgWorker.ReportProgress(i); 
       } 
      }; 
      bgWorker.RunWorkerAsync();      
     } 
    } 

Programı Sınıf

class Program 
    { 
     static void Main(string[] args) 
     { 
      MyObjectBuilder builder = new MyObjectBuilder(); 
      builder.ProgressChanged += new ProgressChangedEventHandler(builder_ProgressChanged);   

      MyObject o = builder.CreateMyObject(); 
      Console.ReadLine(); 
     } 

     static void builder_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      Console.WriteLine(e.ProgressPercentage); 
     } 
    } 
+1

Genelde bir kurucunun veri yüklemesi için kötü bir fikir olduğunu anladım. Er ya da geç pişman olacaksınız - ve eğer birim testi yapıyorsanız, "daha erken" olacaktır. –

cevap

8

Başka bir seçenek elbette çok yapıcı içine olay işleyicileri geçmek olacaktır. Şahsen ben bir kurucu içinde böyle bir şey yapmaktan kaçınmaya çalışıyorum. Yeni bir nesne oluşturmak genellikle arka plan görevlerini başlatmamalı, IMO. Bunun yerine, statik bir yönteme koymak isteyebilirsiniz - ki bu da özel bir kurucuyu çağırabilir.

Ayrıca, sınıfınızı ikiye bölebilirsiniz - her şeyi hazırlayan bir oluşturucu (örneğin olaylar) ve daha sonra Result özelliğine sahip bir "uçuş veya tamamlanmış" sınıfı. İkinci bir örneğini almak için Start ya da birinci sınıfta benzer bir şey ararsınız.

+0

@Jon Bir Builder sınıfı kullanma fikrinizde bir bıçak kullanmayı denedim. Kavramı anladığımı sanmıyorum.Olay işleyiciyi MyObjectBuilder'e aktarıyorum ve sonra bir MyObject öğesini bir oluşturma yöntemiyle döndürüyorum. Ne yazık ki MyObject hala tam olarak dolu değil. Yukarıdaki koduma yapacağınız herhangi bir tweaks? –

+0

@Blake: Olayı MyObject'in bir parçası olarak kullanmayı düşünmüyordum - yalnızca işleyiciyi yapıcıya (MyObjectBuilder.CreateMyObject'den) geçirirdim. Ancak, bu temelde çalışması gereken gibi görünüyor ... neler oluyor? (Bu kodda her iki * yaklaşımı harmanladığınızı unutmayın - örnek kodunuzun başlaması için örnek kodunuzdan memnunsanız, hepsini tek bir türde, belki statik bir yöntemle yapabilirsiniz. Oluşturucunun fikri, onu oluşturmanıza izin vermekti, olay işleyicileri ekleyin ve * sonra * Oluştur yöntemini çağırın.) –

+0

@Jon Ana sorun, Console.WriteLine (o.Result) noktasında çıktı 0'dır. Beklenen 99 yerine (döngü tamamlandıktan sonra). İlerleme doğru şekilde güncelleniyor, sadece nesnenin tam olarak başlatılmamış olması. Nesneye sahip olmak zorunda olduğum bir tasarım hedefini tam olarak başlattı mı, yoksa oluşturucu sürecinin hala inşa aşamasında olduğu anlaşılıyor mu? –

1

Bu mümkün mü? Olabilir. Akıllı mı? No.

En belirgin neden, arka plan iş parçacığının, nesne işleyicisinden sonra olay işleyicileri kullanılmadan önce yürütülmeyeceğinin garanti edilmemesidir. Ya da daha da kötüsü, diğerleri değil, bazı olay işleyicileri abone olabilir.

İlgili konular