2013-11-22 11 views
5

yılında zamanlayıcı olaylarını görmezden nasıl Delphi küresel istisna işleyicisi kurdunuz. Bazı ciddi istisnalarda, bir hata mesajı görüntülenir (ardından Halt()). Hata mesajı gösterilirken, Delphi, daha fazla hataya yol açan, zamanlayıcı olaylarını işleyen ileti sırasını işliyor. Benim istediğimDelphis MessageDlg

zamanlayıcı olaylarını işlemez bir hata iletişim kutusu göstermektir. Delphi'de bu nasıl mümkün olabilir?

Düzelt: İletiyi görüntülemek için Dialogs.MessageDlg (...) kullanıyorum. Böyle

+0

Ben sadece mesajları bu hata iletişim hitaben o geçecekmiş böylece "Nihai Hata Mesajı görüntülenir" ve App'ın OnMsg yolunu kesmek bazı küresel bayrağı olması gerektiğini düşünüyorum Eğer 'TTimer' (ler) kullanırsanız diğer iletiler, özyinelemeli' tüm devre dışı olabilir dışarı http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Forms_TApplication_OnMessage.html –

+2

filtreleme yaparsınız Diyaloğu göstermeden önce 'Uygulama' için TTimer 'i seçin. Sadece bir düşünce. – kobik

+0

@kobik Ardından, global istisna işleyicimin her bir TTimer'den haberdar olması gerekir. Diğer çözümleri tercih ederim. –

cevap

4

Sen sıraya filtre uygulayıp edebilirsiniz mesajları,.

procedure TMainForm.ApplicationMessage(var Msg: TMsg; var Handled: Boolean); 
begin 
    if ShowingFatalErrorDialog then 
    if Msg.Message = WM_TIMER then 
     Handled := True; 
end; 

doğrudan Application.OnMessage bu olay işleyicisi atamak veya bir TApplicationEvents nesnesini kullanın Ya.

Açıkçası ShowingFatalErrorDialog için uygulanmasını sağlamak gerekecek ama bunun nasıl size açıktır inanıyoruz.

+0

İletişim kutusundaki mesajları filtrelemeyi düşünüyordum. Ancak TApplicationEvents ile, global varslara dayanmadan bu şekilde çalışacaktır. Teşekkürler. –

+0

Bence kara liste yaklaşımı burada bir çıkmaz. Arioch'The Ne düşündüğümü soruya o yorumu yayınlamak istemiştim @ Bir beyaz listesi politikasını yerine –

+0

uygulamalıdır. –

2

deneyin şey: TApplication.OnMessage böyle WM_TIMER olarak

... 
    private 
    FAboutToTerminate: Boolean; 
    end; 

... 

type 
    ESevereError = class(Exception); 

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    Tag := Tag + 1; 
    if Tag > 2 then 
    raise ESevereError.Create('Error'); 
end; 

procedure TForm1.ApplicationEvents1Exception(Sender: TObject; 
    E: Exception); 
begin 
    if (E is ESevereError) and (not FAboutToTerminate) then 
    begin 
    FAboutToTerminate := True; 
    Application.ShowException(E); 
    Application.Terminate; 
    end; 
end; 
+0

Teşekkürler, son uygulamamda tüm istisnaları yutmak fikrinizi kullandım. Ama asıl odak noktamız, ilk satırdaki ölümcül zamanlayıcı olaylarını üretmekti. –

+1

Sanırım "FreeAndNil (E) - kodunuzun bir kısmı yanlış. Belgelere göre sanırım, istisnayı serbest bırakmamanız gerekiyor. Bu benim için bir [erişim ihlali] (http://stackoverflow.com/q/22630972/2523663) yol açar. [Bu açıklama] 'a bir göz atın (http://stackoverflow.com/a/22668566/2523663). –

+0

Teşekkürler! Belki de 'ApplicationEvents.CancelDispatch' AV'yi engellemeye yardımcı olabilir, ancak istisnayı yok etmeyin kesinlikle daha iyi! – NGLN

1

sadece referans: her iki cevap bir karışımıdır aşağıdaki kodu kullanacaktır. TFatalErrorAppEvents ile

procedure SaveShowErrorMessage(...) 
begin 
    with TFatalErrorAppEvents.Create(nil) do //avoid timer and further exceptions 
    try 
     Dialogs.MessageDlg(...); 
    finally 
     Free; 
    end; 
end; 

şöyle:

type 
    TFatalErrorAppEvents = class(TApplicationEvents) 
    protected 
     procedure KillTimerMessages(var Msg: tagMSG; var Handled: Boolean); 
     procedure IgnoreAllExceptions(Sender: TObject; E: Exception); 
    public 
     constructor Create(AOwner: TComponent); override; 
    end; 


constructor TFatalErrorAppEvents.Create(AOwner: TComponent); 
begin 
    inherited; 
    OnMessage := KillTimerMessages; 
    OnException := IgnoreAllExceptions; 
end; 

procedure TFatalErrorAppEvents.IgnoreAllExceptions(Sender: TObject; E: Exception); 
begin 
    //in case of an Exception do nothing here to ignore the exception 
end; 

procedure TFatalErrorAppEvents.KillTimerMessages(var Msg: tagMSG; var Handled: Boolean); 
begin 
    if (Msg.message = WM_TIMER) then 
     Handled := True; 
end;