2010-07-22 23 views
18

Uygulamamda her 2 saniyede bir tetiklenen ve olay işleyicimi HandleTimerEvent() öğesini çağıran bir TTimer var. HandleTimerEvent() işlevi paylaşılan kaynakları değiştirir ve geri dönmeden önce yürütmek için 10 saniye sürebilir. Ayrıca, zaman zaman işlemciden vazgeçmek için olay işleyicisinde Sleep() işlevini çağırıyorum.TTimer.OnTimer olay işleyicisi yeniden mı?

C++ builder'in TTimer nesnesinin olayları arama konusunda nasıl çalıştığından emin değilim, bu yüzden açıkladığım senaryo, özellikle, önceki bir çağrı gelmeden önce HandleTimerEvent() öğesinin çağrılıp çağrılmadığını düşünmeme neden oldu.

soru şeylerin bir çift için aşağı gelir.

TTimer nesne olayları sıraya mu? Bir önceki çağrı döndürdü önce

TTimer nesne benim olay işleyicisi arayabilir miyim?

cevap

31

Bu cevap TTimer hala mesajlar WM_TIMER'i kullanmaya uygulanan varsayar. Uygulama değiştiyse (2005'ten beri), lütfen dikkate almayın.

Hayır, TTimer nesne olayları kuyruğa değil. Windows WM_Timer mesajı tarafından yönlendirilir ve Windows, WM_TIMER iletilerinin ileti sırasına yığılmasına izin vermez. Bir sonraki zamanlayıcı aralığı oluşursa ve Windows bir WM_Timer iletisinin uygulamanın ileti kuyruğunda olduğunu görürse, sıraya başka bir WM_Timer karışıklığı eklemez. Bir TTimer.OnTimer olay önceki olay işleyicisi hâlâ çalışıyor bile görevden aldığı için (WM_PAINT için aynı btw)

Evet, bu mümkün. Etkinlik işleyicinizde, uygulamanın iletilerin işlenmesine izin veren herhangi bir şey yaparsanız, zamanlayıcı etkinliğinize yeniden girilebilir. Açık olanı, olay işleyiciniz Application.ProcessMessages'ı çağırırsa, ancak bundan daha ince olabilir - eğer olay işleyicinizde çağıran herhangi bir şey Application.ProcessMessages'ı çağırırsa veya PeekMessage/GetMessage + DispatchMessage'ı çağırırsa veya kalıcı bir iletişim kutusu açarsa veya işlem dışı bir COM nesnesine bağlı bir COM arabirimini çağırır, ardından uygulama iletisi sıranızdaki iletiler işlenecek ve bir sonraki WM_Timer iletinizi içerebilecek.

basit bir çözüm size zamanlayıcı olay işleyicisi çıktığınızda size zamanlayıcı olay işleyicisi girin ve yeniden etkinleştirin zamanlayıcı nesnesini devre dışı bırakmaktır. Bu, kodunuzun mesaj işleme özelliklerine bakılmaksızın, olay işleyiciniz çalışırken hala zamanlayıcı mesajlarının tetiklenmesini önleyecektir.

+10

+1. Zamanlayıcıyı devre dışı bırakmanın etkinliğini (ya da yapmazsanız neyin yanlış gidebileceğini göstermenin kolaylığını) göstermek için, zamanlayıcı işleyicide bir mesaj kutusu göster. Girişte zamanlayıcıyı devre dışı bırakmazsanız, mesaj kutuları birikecektir. –

+2

Ayrıca, zamanlayıcı olay işleyicisinde reentransı önlemek için boole bayrağı kullanabilirsiniz, ancak zamanlayıcının kendisini devre dışı bırakmak çok daha kolaydır. – dthorpe

+0

TTimer kullanımı için kullanışlı bir TTimerGuard sınıfı olan RAII stili bir sınıf için https://forums.embarcadero.com/thread.jspa?messageID=171751𩻧 adresine bakın. Uygulamanıza bağlı olarak FInterval kullanımını ayarlamanız gerekebilir. –

2

TTimer'i yaygın olarak kullanıyorum. Olayları sıraya almaz. Bir olay işleyicisine teslim edilmesini istiyorsanız, zamanlayıcınızın işine devam edebilmesi için olaylarınızı işleyen bir TThread oluşturun. Zamanlayıcı asenkron olarak değil senkronize olarak çalışır. Zamanlayıcıyı devre dışı bırakmak için

İlgili konular