2009-07-30 21 views
29

Eşzamansız TCP soketleri kullanan küçük bir çok iş parçacıklı uygulama yapıyorum, ancak şu noktaya geleceğim: Bir formdan bir değer okumak için özel bir olay kullanıyorum ve olay tarafından kullanılan temsilci bir dize döndürüyor Bittiğinde. BuradaBir Etkinlikten bir değer döndürür - bunun için İyi Bir Uygulama var mı?

Sorum edilir: doğru mu? Olaylardan değerler döndürmek tamam mı? ya da bunu yapmak için daha iyi bir yolu var mı? (değerleri okumak için forma basit bir temsilci kullanma gibi)

cevap

31

Bu olaylardan değerleri döndürmek için sık sık zor. Pratikte, olaya iletilen bir özel EventArgs kümesine yazılabilir bir özellik eklemeyi çok daha kolay buldum ve olay tetiklendikten sonra - WinForms FormClosing olayının İptal özelliğine benzer şekilde - kontrol ettim.

+8

Lütfen, 'event' bölümüne iletilen bir dizi özel EventArgs üzerinde yazılabilir bir özellik içerecek şekilde detaylandırır mısınız? – Odys

+0

@Odys EventArgument nesnesini özel yapın. Sonuçların yaşadığı bir özellik oluşturun. – Crisfole

15

Düşündüğüm en yakın örnek, WinForms'daki FormClosing olayıdır. Formun eventArgs.Cancel özelliğini true değerine ayarlayarak olayı iptal etmesine izin verir. Benzer bir şey yapabilmeniz için, kendi sınıfınızın sınıfını, o sınıftaki bir özellik olarak dönüş değeriyle sınıflandıracaksınız. Ardından, etkinliği her açtığınızda bir olay args nesnesini geçirin. Olayı kim hazırladıysa, olayın dönüş değeri için nesne olup olmadığını denetleyebilir. Etkinliği alan diğer kişiler de olay arşiv nesnesini inceleyebilir veya değiştirebilir.

Güncelleme: Sadece AppDomain.AssemblyResolve olayına rastladım ve bir değer döndüren bir olay gibi görünüyor. Bir değer döndüren bir temsilci türü bildirmeniz ve ardından etkinliğinizi bu temsilci türüyle tanımlamanız gerektiği görünüyor. Yine de kendi olayımı yaratmayı denemedim. Etkinlik argümanında bir mülk kullanmanın bir avantajı, etkinliğe giden tüm abonelerin önceki abonelerin geri döndüklerini görebilmeleridir.

+1

Not: olayları tanımlamak için herhangi bir temsilci kullanmak, nedenle de kamu olay Func 'gibi bir olay tanımlamak iyi olurdu someEvent;' olarak çağrılabilir olacağını 'bool r = SomeEvent ("foo", "bar"); ' –

26

Bunun iyi bir fikir olduğunu sanmıyorum ... olaylar temelde çok noktaya yayın delegeleridir, bu nedenle birden çok işleyici olabilir. Bu durumda hangi dönüş değerini alacaksınız?

6

bu en iyi yöntem ise bilmiyorum ama ben bu şekilde yaptım.

Func<DataRow, bool> IsDataValid; 

    // some other code .... 

    isValid = true; 
    if (IsDataValid != null) 
    { 
     foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList()) 
     { 
     isValid &= func(Row); 
     } 
    } 
-1
void method() 
{ 
    list<string> strings = new list<string>(); 

    dostuff += stuff; 
    dostuff += stuff; 

    dostuff(this, new EventHandlerArgs(){ Parameter = strings }) 

    foreach(string currString in strings) 
    { 
      //.... 
    } 
} 

void stuff(object sender, EventHandlerArgs e) 
{ 
    list<string> strings = e.Parameter as list<string>; 

    if (strings != null) 
    { 
     strings.Add(MyString) 
    } 
} 
+2

Yığın akışına hoş geldiniz! Mesaj doğruluğunu artırmak için örnek bir kod için kısa bir açıklama sağlamak her zaman daha iyidir :) –

10

Ben bu yazı ama başkası bu parçacığı genelinde gelirse için Dustin Campbell cevabı açıklamak için koduyla yorumunu ekleyerek düşüncesi sonra yaşları olduğunu biliyoruz. En iyi uygulamaların hangisi olacağına karar vermeye çalışırken bu yazıya rastladım ve cevapla kastedilen şey buydu.

etkinliğinizin temsilci oluştururken

public class myCustomeEventArgs:EventArgs 
{ 
    public bool DoOverride { get; set; } 
    public string Variable1 { get; private set; } 
    public string Variable2{ get; private set; } 

    public myCustomeEventArgs(string variable1 , string variable2) 
    { 
     DoOverride = false; 
     Variable1 = variable1 ; 
     Variables = variable2 ; 
    } 
} 

Yani bunun gibi yaratılan olay args kullanmak kendi özel olay işleyicisi sınıf oluşturun.

public delegate void myCustomeEventHandler(object sender, myCustomeEventArgs e); 

Etkinliği yükselttiğiniz sınıfta da olayı bildirirsiniz.

public event myCustomeEventHandler myCustomeEvent; 

Yani sınıfta olay olayını dinler sınıf tetiklemek zaman yapabilirsiniz sadece belirlenen olayın gövdesinde e.DoOverride = true; olayı ateşleyen sınıfta beyan edileceği gibi.örneğin

Yangın olay: Olay bir değer döndürür ve orada birden işleyicileri olan olayı kayıtlı

if(myCustomeEvent != null) 
{ 
    var eventArgs = new myCustomeEventArgs("Some Variable", "Another Varaible"); 
    myCustomeEvent(this, eventArgs); 
    //Here you can now with the return of the event work with the event args 
    if(eventArgs.DoOverride) 
    { 
     //Do Something 
    } 
} 
+0

Etkinliğin ne zaman "geri döneceğini" nasıl anlarsınız? –

+4

Olaylar, onları uyandıran aynı iş parçacığında çalıştırılır. 'MyCustomeEvent (...)' komutunu çalıştıran kod, abone olunan tüm olay işleyicilerine (aynı iş parçacığı üzerinde çalışır) denetimi geçirir. Tüm kodları çalıştırıldıktan sonra, kontrol 'myCusomeEvent (...)' çağrısından hemen sonra talimata dönecektir. Aboneler yoksa veya etkinliği başka bir iş parçacığına yeniden yayınlayan aboneler varsa, o zaman "eventArgs" üzerindeki tüm özellikler varsayılan değerlerine sahip olacaktır ("bool" ve false için "null"). –

6

Not: yalnızca son olay sonucu döndürür.

class Program 
{ 
static event Func<string, bool> TheEvent; 

    static void Main(string[] args) 
    { 
     TheEvent += new Func<string, bool>(Program_TheEvent); 
     TheEvent +=new Func<string,bool>(Program_TheEvent2); 
     TheEvent += new Func<string, bool>(Program_TheEvent3); 
     var r = TheEvent("s"); //r == flase (Program_TheEvent3) 
    } 

    static bool Program_TheEvent(string arg) 
    { 
     return true; 
    } 

    static bool Program_TheEvent2(string arg) 
    { 
     return true; 
    } 

    static bool Program_TheEvent3(string arg) 
    { 
     return false; 
    }   
} 
+0

Teşekkürler. Bir WCF servisi boyunca çalışıyorum – harveyt

+1

Teşekkürler! Hangi olay işleyicisinin "kazanacağını" merak ediyordum. –

0

EventArgs özelliklerini buradan özümsedim ve X ve Y değerlerini çıkardım.

private void navBarControl1_Click (object sender, EventArgs e) { int _x = 0; int _y = 0;

 Type t = e.GetType(); 
     IList<PropertyInfo> props = new List<PropertyInfo>(t.GetProperties()); 

     foreach (PropertyInfo prop in props) 
     { 
      if (prop.Name == "X") 
      { 
       object propValue = prop.GetValue(e, null); 
       _x = Convert.ToInt32(propValue); 
      } 
      if (prop.Name == "Y") 
      { 
       object propValue = prop.GetValue(e, null); 
       _y = Convert.ToInt32(propValue); 
      } 
     } 
+2

lütfen cevabınızı daha net hale getirin – Mostafiz

İlgili konular