Announcement

Collapse
No announcement yet.

Connection Points / COM-Server Events

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

  • Connection Points / COM-Server Events

    hallo,

    kann mir jemand einen Tip zur folgenden Problemstellung geben:
    Ein COM-Client soll eine Interfacemethode eines COM-Servers zum Start einer länger andauerenden Verarbeitung aufrufen (z.B. Start eines Threads der diese Verarbeitung durchführen soll). Die Interfacemethode wird sofort wieder beendet, ohne somit den Client über die lange Verarbeitungsdauer zu blockieren. Sobald die Verarbeitung im COM-Server beendet ist, soll dieser dies dem COM-Client über einen Event melden.

    Ich habe einen COM-Server mit Eventverarbeitung sowie einen zugehörigen COM-Client mit einem Sinkobjekt erstellt. Und die Events vom COM-Server funktionieren auch einwandfrei sofern diese innerhalb der Implementierungs-methoden des COM-Servers aufgerufen werden. Ich habe es leider nicht geschafft die Events außerhalb der Implementierungsmethoden des Servers z.B. von der Klasse FormMain aus über z.B. einen Button aufzurufen.

    Für einen Tip wäre ich sehr dankbar.

    Gruß Conny

  • #2
    Hallo,

    das folgende Beispiel demonstriert, wie man über die Benutzeroberfläche (Formular) des COM-Servers ein Event für die Connection Point-Schnittstelle von Hand (Button) auslösen kann: <br>
    1. Das COM-Objekt stellt eine öffentliche Methode bereit, die vom Formular aus aufgerufen werden kann (Bsp: <i>GUIEvent</i>)<br>
    2. Das COM-Objekt speichert einen Zeiger auf das eigene Objekt in einer globalen Variable (<i>gObjRef</i>)<br>
    3. Das Formular des COM-Servers greift über diese globale Variable (und <b>nicht</b> über das Interface des COM-Objekts) auf die Instanz des COM-Objekt zu, so dass die öffentliche Methode <i>GUIEvent</i> direkt aufgerufen werden kann.

    <b>COM-Objekt</b>
    <pre>
    unit CPmitGUI_Impl;

    interface

    uses
    ComObj, ActiveX, AxCtrls, Classes, CPmitGUI_TLB, StdVcl;

    type
    TCPwithGUI = class(TAutoObject, IConnectionPointContainer, ICPwithGUI)
    private
    { Private-Deklarationen }
    FConnectionPoints: TConnectionPoints;
    FConnectionPoint: TConnectionPoint;
    FSinkList: TList;
    FEvents: ICPwithGUIEvents;
    FSrvMsg : String;
    public
    procedure Initialize; override;
    procedure GUIEvent;
    protected
    { Protected-Deklarationen }
    property ConnectionPoints: TConnectionPoints read FConnectionPoints
    implements IConnectionPointContainer;
    procedure EventSinkChanged(const EventSink: IUnknown); override;
    procedure DoWork(const sText: WideString); safecall;
    end;

    var
    gObjRef : TCPwithGUI;

    implementation

    uses ComServ;

    procedure TCPwithGUI.EventSinkChanged(const EventSink: IUnknown);
    begin
    FEvents := EventSink as ICPwithGUIEvents;
    if FConnectionPoint <> nil then
    FSinkList := FConnectionPoint.SinkList;
    end;

    procedure TCPwithGUI.Initialize;
    begin
    inherited Initialize;
    gObjRef := Self;
    FConnectionPoints := TConnectionPoints.Create(Self);
    if AutoFactory.EventTypeInfo <> nil then
    FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
    AutoFactory.EventIID, ckSingle, EventConnect)
    else FConnectionPoint := nil;
    end;

    procedure TCPwithGUI.DoWork(const sText: WideString);
    begin
    FSrvMsg := sText;
    if FEvents <> nil then
    FEvents.OnWork(FSrvMsg);
    end;

    procedure TCPwithGUI.GUIEvent;
    begin
    if FEvents <> nil then
    FEvents.OnWork(FSrvMsg);
    end;

    initialization
    TAutoObjectFactory.Create(ComServer, TCPwithGUI, Class_CPwithGUI,
    ciMultiInstance, tmApartment);
    end.
    </pre>
    <b>Formular des COM-Servers</b>
    <pre>
    uses CPmitGUI_Impl;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    gObjRef.GUIEvent;
    end;
    </pre&gt

    Comment


    • #3
      super,

      danke für die ausführliche Hilfe

      Gruß Conn

      Comment


      • #4
        Hallo,

        ich bin verzwifelt damit beschäftigt dieses Demoprogramm zum Laufen zu bringen. Das Problem das ich habe ist eine Zugriffsverletzung bei der Abfrage von FEvent in der procedure TCPwithGui.GuiEvent .
        In Verwendung habe ich Delphi6 mit Servicepack2.

        Für Tips wäre ich sehr dankbar

        Ingemar Zotte

        Comment


        • #5
          Hallo,

          ich bin verzweifelt damit beschäftigt dieses Demoprogramm zum Laufen zu bringen. Das Problem das ich habe ist eine Zugriffsverletzung bei der Abfrage von FEvent in der procedure TCPwithGui.GuiEvent . In Verwendung habe ich Delphi6 mit Servicepack 2.

          Für Tips wäre ich sehr dankbar

          Ingemar Zotte

          Comment


          • #6
            Hallo,

            ich bin verzweifelt damit beschäftigt dieses Demoprogramm zum Laufen zu bringen. Das Problem das ich habe ist eine Zugriffsverletzung bei der Abfrage von FEvent in der procedure TCPwithGui.GuiEvent . In Verwendung habe ich Delphi6 mit Servicepack 2.

            Für Tips wäre ich sehr dankbar

            Ingemar Zotte

            Comment


            • #7
              Hallo,

              ich bin verzweifelt damit beschäftigt dieses Demoprogramm zum Laufen zu bringen. Das Problem das ich habe ist eine Zugriffsverletzung bei der Abfrage von FEvent in der procedure TCPwithGui.GuiEvent . In Verwendung habe ich Delphi6 mit Servicepack2.

              Für Tipps wäre ich sehr dankbar

              Ingemar Zotte

              Comment


              • #8
                Hallo,

                hinter FEvents steckt ein Interface-Zeiger, der erst dann "scharf" ist, wenn sich ein Client an die ConnectionPoint-Schnittstelle angekoppelt hat. Daher muss das eigene Objekt prüfen (<> nil), ob dieser Interface-Zeiger für den Rückruf genutzt werden darf:
                <pre>procedure TCPwithGUI.GUIEvent;
                begin
                if <b><font color="#FF0000">FEvents &lt;&gt; nil</font></b> then
                FEvents.OnWork(FSrvMsg);
                end;
                </pre&gt

                Comment


                • #9
                  Hallo,

                  danke für den Tipp. Ich konnte das Problem mit der Zugriffsverletzung inzwischen lösen. Mußte eigentlich nur bei der On Create in Form 1 das Objekt erzeugen.

                  procedure TForm1.FormCreate(Sender: TObject);
                  begin
                  cpmitGui_impl.TCPwithGui.Create;
                  end;

                  Ingema

                  Comment


                  • #10
                    Hallo

                    >>3. Das Formular des COM->>Servers greift über diese >>globale Variable (und nicht >>über das Interface des COM->>Objekts)

                    >>globale Variable (und nicht >>über das Interface des COM->>Objekts)

                    Eine Frage.
                    Wie wichtig ist es ("nicht über das Interface") ?

                    Was spricht dagegen
                    gObjRef als Interface variable zu definieren?

                    gObjRef : ICPwithGUI;

                    Gibt es da spezifische Probleme ?

                    Dank

                    Comment


                    • #11
                      Hallo,

                      &gt;Wie wichtig ist es ("nicht über das Interface") ?

                      diesen <B>Sonderfall</b> benötigt man nur dann, wenn die Benutzeroberfläche (Formular) des COM-Servers direkt ein Event auslösen soll, um die aktiven ConnectionPoint-Clients zu benachrichtigen:
                      <pre>
                      <b>uses</b> CPmitGUI_Impl;
                      <br>
                      <b>procedure</b> TForm1.Button1Click(Sender: TObject);
                      <b>begin</b>
                      gObjRef.GUIEvent;
                      <b>end</b>;
                      </pre&gt

                      Comment

                      Working...
                      X