Announcement

Collapse
No announcement yet.

ADO Express u. CommandTimeout im Thread benutzen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • ADO Express u. CommandTimeout im Thread benutzen

    Hallo,
    ich baue in einem Thread eine Datenbankverbindung mittels ADO-Express auf.
    Da die Anwendung zeitkritisch ist, setze ich
    das Property "CommandTimeout". Leider bemerke ich keinerlei Unterschied, egal wie ich die Einstellungen mache.
    Kann es sein, daß der Thread vom System die erforderlichen Nachrichten nicht bekommt?
    Wenn ja, wie kann ich das implementieren?

    Helmut

  • #2
    Hallo,

    funktioniert der Timeout im Hauptfenster der Anwendung (die Verwendung des geänderten Timeout-Wertes hängt von der verwendeten Delphi-Version und den eingespielten inoffiziellen ADO Express-Patches ab)?

    Wenn ja, bedient der Thread in seiner Excute-Methode die Botschaftswarteschleife, damit die COM-Events erkannt werden können

    Comment


    • #3
      Hallo,

      ich benutze Delphi 5 + Service Pack 1.
      Für ADO habe ich einen Patch (V51_Backup) eingespielt.
      Der Thread fragt die Botschaftswarteschleife nirgens ab.
      Was ist damit genau gemeint?
      Dort könnte der Fehler liegen ??

      Helmu

      Comment


      • #4
        Hallo,

        die ADO-Objekte werden im Normalfall in einem <i>Single-threaded Apartment</i> (STA, alias Apartment Model) betrieben. COM stellt an STA in Bezug auf Windows-Botschaften bestimmte Anforderungen und legt Regeln fest:

        1. Ein STA-Thread, der keine Botschaften aus der Warteschlange ausliest und verteilt, kann zum Hängenbleiben von anderen Anwendungen führen, wenn diese via Broadcast eine Botschaft an alle Top-Level-Fenster verschicken.

        2. Ein STA-Thread, der keine Botschaften aus der Warteschlange ausliest und verteilt, hinterläßt eine kleine Speicherleiche.

        3. Ein STA-Server-Thread, der keine Botschaften aus der Warteschlange ausliest und verteilt, kann keine Aufrufe von Clients aus anderen Apartments erkennen.

        4. Ein STA-Client-Thread, der keine Botschaften aus der Warteschlange ausliest und verteilt, kann keine Benachrichtungen von Servern erhalten.

        Im Hintergrund erzeugt COM für jeden STA-Thread (also ein Thread, der CoInitialize/CoInitiliazeEx aufgerufen hat) ein verstecktes Top-Level-Fenster. Wenn nun eine Anwendung eine Windows-Botschaft wie zum Beispiel WM_DDE_INITIATE als Rundruf (Broadcast) verschickt, bleibt die SendMessage-Funktion dieser Anwendung solange hängen, bis alle Top-Level-Fenster auf diese Botschaft reagiert haben! Um diese nachteiligen Folgen für andere Anwendungen zu vermeiden, fordert COM, daß STA-Threads Windows-Botschaften verteilen. COM setzt die Aufrufe von Server-Methoden in RPC-Aufrufe (Remote Procedure Call) um. Im Apartment-Modell synchronisiert COM die empfangenen RPC-Aufrufe für den Empfänger-Thread, indem dem Thread eine Windows-Botschaft zugestellt wird. Dies bedeutet jedoch auch, daß ein STA-Server-Thread immer dann keine Aufrufe von außerhalb erkennen kann, wenn er die Botschaftswarteschlage des versteckten Fensters nicht ausliest. Das gleiche gilt für einen STA-Client-Thread, der dann in diesem Fall keine Benachrichtigungen des Servers verarbeiten kann.

        Der eigene Thread müsste etwas in dieser Art machen, um Aufrufe erkennen zu können:
        <pre>
        <b>var</b>
        dwTime : DWORD;
        dwResult : DWORD;
        aMsg : TMsg;
        aHandle : THandle;
        bTimeOut : Boolean;
        <b>begin</b>
        bTimeOut := False;
        dwTime := Time * 1000;
        aHandle := GetCurrentThread;
        <b>repeat</b>
        dwResult := MsgWaitForMultipleObjects(1, aHandle, False, dwTime, QS_ALLINPUT);
        <b>case</b> dwResult <b>of</b>
        WAIT_OBJECT_0 + 1 : <b>while</b> PeekMessage(aMsg, 0, 0, 0, PM_REMOVE) <b>do</b>
        <b>begin</b>
        TranslateMessage(aMsg);
        DispatchMessage(aMsg);
        <b>end</b>;
        WAIT_TIMEOUT : bTimeOut := True;
        <b>end</b>;
        <b>until</b> bTimeOut;
        CloseHandle(aHandle);
        <b>end</b>;
        </pre>
        P.S: Die ganzen Hintergründe dazu sowie einige Beispiele sind in meinem Buch <i>COM/DCOM/COM+ mit Delphi</i> zu finden

        Comment


        • #5
          Hallo Andreas,

          nun glaube ich, ich habe ein großes Problem!
          Ich hoffe ich habe das richtig verstanden.
          Was habe ich für Möglichkeiten, die Nachrichtenwarteschlange abzufragen.
          Die Implementierung ist doch in der procedure Execute, so dort wird nun CoInitialize aufgerufen. Anschliessend die ADO-Objekte instanziert und eingestellt. Dann wird ADODataSet.Open aufgerufen. Nun ist mir nicht klar, wie dein Beispiel da eingebaut werden kann?
          Genügt es vorher und nachher einen aufruf wie
          PeekMessage(aMsg, 0, 0, 0, PM_REMOVE) zu machen ?

          Helmu

          Comment


          • #6
            Hallo Andreas,
            ich benute in der Anwendung (Thread) die ADO-Express Komponenten
            nun habe ich in der Unit ADODB eine Procedure
            "WaitForConnectComplete" gesehen. In der wird
            wiederum ein Application.ProcessMessage aufgerufen.
            Demnach müsste doch die Nachrichtenwarteschlange
            spätestens beim öffnen der ADOConnection für den
            Thread angelegt und ausgelesen werden? Kann man das so sehen? Wenn ich Dich also richtig
            verstehe, müsste man nun vor und nach jedem länger andauernden
            SQL ein Applications.ProcessMessage aufrufen?
            Könnte das eine Verbesserung bringen?

            Helmu

            Comment

            Working...
            X