2009-02-25 17 views
2

Es gibt zwei Verfahren, A1 und A2, die beide Anruffunktion B in ihrem Code:Was ist der beste Weg, eine Prozedur "verzögert" zu nennen?

function B: boolean; 
begin 
    // do other stuff 
end; 

procedure A1; 
begin 
    // do stuff 
    if b then 
    ... 
    // do stuff 
end; 

procedure A2; 
begin 
    // do stuff 
    if b then 
    A1; // <- how to call A1 "delayed"? 
    // do stuff 
end; 

Wenn die Bedingung in A2 wahr ist, Verfahren A1 genannt werden müssen, aber das würde passieren, während A2 noch läuft was ich nicht will.

Was passiert ist: Wenn die Bedingung in A2 wahr ist, dann sollte A2 beendet sein und nach Verlassen von A2 sollte die Prozedur A1 aufgerufen werden.

Eine hässliche Lösung wäre, einen Timer zu setzen, der A1 nach einer Verzögerung aufruft, die sicherstellt, dass A2 beendet ist.

Aber es muss bessere Wege geben, oder?

BEARBEITEN: A1 und A2 sind in meinem Fall Ereignisse, also werden sie nicht per Code aufgerufen und ich kann A1 nicht einfach von einer aufrufenden Prozedur aufrufen, nachdem A2 beendet ist.

Antwort

12

Angesichts Ihrer Einschränkungen klingt es so, als ob Sie vor der Rückkehr PostMessage als letzte Sache in A2 anrufen möchten. Die PostMessage Parameter sollten so eingerichtet werden, dass das Ereignis A1 ausgelöst wird. Das einzige, worüber man sich Sorgen machen muss, ist eine Race Condition, aber ich bin mir nicht sicher, ob das ein Problem mit der Windows Message Queue sein wird.

+0

geprüft Ich glaube nicht, gäbe es eine Race-Bedingung sein. PostMessage ist der Weg zu gehen. Die Nachrichtenwarteschlange wird verarbeitet, sobald der A2-Ereignishandler abgeschlossen ist oder ein manueller Aufruf an Application.ProcessMessags erfolgt. –

0

Sie könnten ein boolesches Flag verwenden: Setzen Sie "A1_should_run", wenn A2 läuft, und überprüfen Sie das Flag am Ende von A2. Diese Lösung ist einfach, aber irgendwie hässlich, weil sie dem Code Nichtlokalität hinzufügt und nicht sehr gut auf komplexere Situationen anwendbar ist.

Sie können eine Anrufwarteschlange verwenden: A1 und A2 werden immer ausgeführt, indem Sie in die Warteschlange gestellt werden. In diesem Fall wird einfach A1 in die Warteschlange gestellt. Diese Lösung ist für Ihren Fall nicht so einfach, trifft aber sehr gut auf kompliziertere Situationen zu.

0

Ich habe ähnliche Probleme in der Vergangenheit durch Erstellen einer verzögerten Methode Aufrufeinheit behandelt. Es kann übertrieben sein, wenn Sie es nur an einem Ort brauchen, aber es ist eine nützliche Sache zu haben.

In meinem Fall würde ich

procedure A2; 
begin 
    // do stuff 
    if b then 
    DelayedCall('A1' {identifier}, A1 {event}, 0 {ms delay}, [] {various function flags}); 
    // do stuff 
end; 

Intern DelayedCall Orte A1 auf eine geordnete Liste (geordnet nach Zeit wegen) schreiben. Ein Timer fragt die Liste ab (mit einer variablen Frequenz, abhängig davon, wann das erste Ereignis fällig ist) und führt fällige Ereignisse aus.

Es ist keine schrecklich komplizierte Funktion zu schreiben, aber es kann sehr nützlich sein.

Bearbeiten: In dem Beispiel bereitgestellt würde eine PostMessage früher verwenden. Der DelayedCall wird erst nach Abschluss von A2 ausgeführt (es sei denn, A2 verfügt über einen ProcessMessages- oder Sleep-Aufruf), aber er wird möglicherweise nicht sofort ausgeführt, nachdem A2 beendet wurde, je nachdem, was sonst noch passiert. Allerdings verwende ich häufig einen DelayedCall in ähnlichen Szenarien.

Weder Postmessage oder DelayedCall passieren wird sofort, sie beide müssen warten, bis die Nachrichtenschleife

+0

Das Problem mit einem Timer ist, dass man nie weiß, was sonst noch im System passiert und wann A2 fertig sein wird.PostMessage wird den Anruf direkt hinter das Ende von Ereignis A2 setzen, wenn die Nachrichtenwarteschlange das nächste Mal behandelt wird. – Holgerwa

Verwandte Themen