2009-02-16 22 views
8

olayları çıkarıp Aşağıdaki kod var: Im eklemeye çalışırken aptal bir şey yapıyor iseC# ekleme ve Bugün bir zamanlayıcı olayları çıkarmak için çalışıyorum bir zamanlayıcı

Timer myTimer = new Timer(); // Windows.Forms Timer 

public void addEvent(MyDelegate ev) 
{ 
    myTimer.Tick += new EventHandler(ev); 
} 

public void removeEvent(MyDelegate ev) 
{ 
    myTimer.Tick -= new EventHandler(ev); 
} 

Bilmiyorum ve bu şekilde delegeleri kaldırmak, delegeler ekleyebilir ve beklendiği gibi ateş etmelerini sağlayabiliyorum. Ancak, olayları kaldırmaya çalıştığımda, Zamanlayıcılar Kene üzerinde ateş etmeye devam ederler.

Açıkça yanlış bir şey gören var mı?

+0

Eğer MyDelegate ait tanımını gösterir ve neden orada olduğunu açıklayabilir misiniz? –

cevap

8

Bu kod inanıyoruz. Mevcut bir EventHandler'ı asla kaldırmaz. eklenti için, sen, sen EventHandlers geçen gerektiğini değil MyDelegates istediğiniz işlevselliği alın ve kaldırmak için yöntemler: İn geçirebilmesi için

Timer myTimer = new Timer(); // Windows.Forms Timer 

public void addEvent(EventHandler ev) 
{ 
    myTimer.Tick += ev; 
} 

public void removeEvent(EventHandler ev) 
{ 
    myTimer.Tick -= ev; 
} 

çağıran kodu, EventHandlers iz ekledi tutmak zorunda kalacak abonelikten çıkma zamanı geldiğinde aynı EventHandler nesnesi.

+1

Kod, olduğu gibi çalışır - arama kodunun Eventhandlers listesini tutmasına gerek yoktur. Etkinliğin backingstore fiili temsilci arar ve proprt ivocationItem'i siler. RemoveEvent (MyTickHandler) öğesini çağırabilirsiniz; –

+0

Orada kodlayıcı-blok anı yaşadığımı biliyordum! Delegeler yerine EventHandlers kullanmanın doğru olduğunu söylüyorsunuz. Yardım ettiğin için teşekkür ederim! –

1

Sadece çok sevdiği hatta taşıma yönteminin adını başvurarak abonelikten mümkün olmalıdır:

public void removeEvent(MyDelegate ev) 
{ 
    myTimer.Tick -= ev as EventHandler; 
} 
+0

Unfortunatly bu bir derleyici hatası üretir "örtülü 'myDelegate' '' System.EventHandler '' türüne dönüştürülemiyor ' –

+0

Bu hiçbir fark yaratmaz. Yeni EventHandler (...) veya benzer kurucular atlarsanız, derlediğinizde bunlar eklenir. – Samuel

+0

Yine de yapabilir misin? –

0

Eğer temsilci her zaman için yeni bir sarmalayıcı yaratıyor ekleme ve olay işleyicileri çıkarmadan. Bu nedenle, kaldırma yönteminizde, etkinlik için hiç bir zaman dinleyici olarak eklenmemiş olan yeni EventHandler nesnesini kaldırmaya çalışıyor.

Bu kurulum türünü kullanmaya devam etmek istiyorsanız, EventHandlers'ınızı bir Sözlüğe yapıştırabilirsiniz. AddEvent yönteminde, yeni oluşturulan EventHandler öğenizi sözlüğünüze ve removeEvent yöntemine yapıştırın, EventHandler öğesini sözlüğünden çekin ve bunu yeni bir örnek oluşturmak yerine kaldırın.

myTimer.Tick -= new EventHandler(ev); 

yeni EventHandler nesnesi oluşturur:

2

Sorununuz, bunu yapmak için yardımcı yöntemler kullanmaktan geliyor. Bunlar olmadan, beklendiği gibi çalışır, onlarla ne yapması gerektiğini bilmiyor.

Bunu düzeltmek için, bu değeri daha sonra kaldırabilmeniz için, kancalama yönteminde oluşturulan EventHandler değeri olan bir sözlüğü korumanız gerekir. gibi

şey: eleman varsa

var handlers = new Dictionary<MyDelegate, EventHandler>(); 

public void addEvent(MyDelegate ev) 
{ 
    var handler = new EventHandler(ev); 
    handlers.Add(ev, handler); 
    myTimer.Tick += handler; 
} 

public void removeEvent(MyDelegate ev) 
{ 
    myTimer.Tick -= handlers[ev]; 
} 

Uygun kontrolleri eklemek gerekir.

Ayrıca, parametre türünü de değiştirebilirsiniz ve beklendiği gibi çalışır.

public void addEvent(EventHandler ev) 
{ 
    myTimer.Tick += ev; 
} 

public void removeEvent(EventHandler ev) 
{ 
    myTimer.Tick -= ev; 
} 

addEvent(new EventHandler(...)); 
removeEvent(new EventHandler(...)); 
0

Sana yanlış yaptığını bilmiyorum, ama ben sayaçları için kullanacağı zamanki yaklaşım Tick olaya abone ve sonra almak istemediğinizde Timer devre dışı bırakmak olacaktır Olaylar, yaptığınız zaman yeniden etkinleştiriliyor.

Etkinliğe bağlanan birden fazla etkinlik işleyiciniz varsa, ancak bazı kullanımları umarız size yardımcı olmaz.

3

ilk kod Takip sanki uzun addEvent ve removeEvent geçirilen MyDelegate 'ev' ile aynı nesne örneği örneği içeren bir sınıf düzeyinde MyDelegate alan varsa Örneğin (veya, gayet iyi çalışıyor Burada birkaç tane daha tavsiye ve MyDelegate nesnesini bir Dictionary'de saklayın.

addEvent(new MyDelegate(this.HandlerMethod)); 
// ... do some stuff 
removeEvent(new MyDelegate(this.HandlerMethod)); 

Hangi durumda addEvent ve removeEvent hangi nokta EventHandler delege yaratıyor:

Sorun kodu addEvent ve removeEvent böylece gibi bazı işleyici yöntemine işaret yeni MyDelegate örneklerini geçiyor sesleniyor şüpheli Farklı yöntem adresleri, bu delegeler sırayla aynı yönteme işaret etse bile (this.HandlerMethod). Bunun nedeni, EventHandler delegelerinin add ve remove delegelerinin, adresine doğrudan değil, farklı MyDelegate örneklerinde MyDelegate.Invoke() yöntemine nokta oluşturmasıdır.

+1

Şakanın şüphesine ek olarak, bu durum, arayan kişinin yalnızca temsilci imzasıyla eşleşen bir yöntemin adını, örn., AddEvent (this.MyCallback); Bu durumda, delege örtülü olarak oluşturulur ve açıklanan soruna yol açar. –

0

Bu çalışması gerekir:

private void timer_Tick(object sender, EventArgs e) 
{ 
    try 
    { 
     // Disallow re-entry 
     timer.Tick -= timer_Tick; 
     . . . 
    } 
    finally 
    { 
     timer.Tick += timer_Tick; 
    } 
}