• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 474
  • Last Modified:

COM callback with in-process server

We have an in-process server written in D3. We are using connection points to tell the client to take a particular course of action. In order to avoid the server being locked, we had to do run the callback routine on another thread. This I did by marshaling over the interface onto a thread that then makes the callback, and terminates. With an out of process server, all is fine, but with an in-process the problem is that although the reference count is set to 0 (we have tried forcing this) the server does not unload. If it is invoked again, a 2nd instance starts up and so on... We have tried CoFreeUnusedLibraries to no avail. I've tried the same approach in Delphi 4 with mixed results because sometimes it works, sometimes I get an access violation. We are having to go with an out of process server at the moment, but really want to use in-process. Any ideas?
1 Solution
Relating to a recent interesting discussion on Ex-Ex, Madshi pointed out that you don't need to (ever?) call _AddRef or _Release in Delphi, because Delphi handles reference counts for you.  Have you tried removing all calls to _AddRef & _Release in your Delphi 4 project?  It might remove your Access Violations.


how do you create your thread? Do do use Delphi's TThread object or win API CreateThread? In the latter case: Have you set the variable "isMultiThread:=true" and have you closed the thread handle that is returned from CreateThread?

If neither JimBob's (hi, JimBob :-) nor my comment helps you, perhaps you can provide some source code?

Regards, Madshi.
pythagorusAuthor Commented:
We are using Delphi threads and have tried both with and without using _AddRef & _Release. The thread executes, does the callback and terminates.

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Perhaps the thread makes problems? Remember, the Delphi VCL is not thread safe. What are you doing in the thread exactly? Can you please give us the code of the thread creation and of the thread execute function?

Regards, Madshi.
P.S: As JimBob said, please remove the _AddRef/_Release calls, regardless of your problem. Otherwise Delphi could get problems...
pythagorusAuthor Commented:
I have created a new server, without all my implementation code.
The problem seems to be down to the connection and channel not being freed up.
Connection is of type Iconnection but is created as a Tconnection. Cannot cast the IConnection to a TConnection to free it - that just crashes.

We are using code obtained from Binh Ly which makes use of connection points. We have sent code to Binh, but he does not have a solution. Incidently, we have just found the same problem with an out-of-process server.

constructor TCallbackThread.Create(ConnectData: TConnectData; TaskID: String;
  Message: String; COMObject: IDispatch);
  inherited Create(True);
  // Bring in the Callback Event Interface
  FConnectData := ConnectData;
  // TaskID
  FTaskID := TaskID;
  // And the Message Text itself
  FMessage := Message;
  // Create the Marshaler with the appropriate Interfaces
  FMarshaler := TMarshaler.CreateMarshalObject (IDispatch, COMObject);
  // Now its safe to use the COM interface that was outside the Apartment

procedure TCallbackThread.Execute;
  ifDisp: IDispatch;
  // Tell COM whats going on
  // Get the Interface as IDispatch
  ifDisp := FConnectData.pUnk as IDispatch;
  // Marshall the Interface into this Apartment
  FMarshaler.UnMarshalObject (ifDisp);
  // Do the Callback
  IDispEvent (ifDisp).GotMessage (FTaskID, FMessage);
  // Got control back from the Client - All done
  // ifDisp._Release;

destructor TCallbackThread.Destroy;
  // Free the TConnectData's Pointer
  FConnectData.pUnk := nil;
unit CMEvent;


  TMessageEvent = procedure (const UserName, Message : string) of object;

  TEvent = class (TAutoIntfObject, IEvent)
    { IEvent }
    procedure GotMessage (const UserName, Message: WideString); safecall;
    FOnMessage : TMessageEvent;
    constructor Create;
    property OnMessage : TMessageEvent read FOnMessage write FOnMessage;


procedure TEvent.GotMessage (const UserName, Message: WideString);
  if Assigned (OnMessage) then
    OnMessage (UserName, Message);

constructor TEvent.Create;
  ifTypeLib : ITypeLib;
  OleCheck (LoadRegTypeLib(LIBID_CMServer, 1, 0, 0, ifTypeLib));
  inherited Create (ifTypeLib, IEvent);

Firstly, for everyones benefit, the address of Bihn's site is


I have managed to use objects based on his with excellect results, though it took a while to get it all going. From the code extract it seems that you wish to delegate the callback to a thread off of the main application thread.

The problem here is with the objects that implement the connection and channel interfaces. If you refer to Bihns original code, you will find that the ChatChannel object, the one returned by the ChatConnection.ChatChannel is declared as a const. If you try to hold on to the Connection or Channel objects so that you can "give them" to the thread with the delegation responsibility, then the server, whether in or out of process, will not unload properly even if you assign "Unassigned" to variants or "nil" to interfaces - which one will depend on the types of the Connection/Channel. To do the callback, you only need to use the Channel unit, and call Channel.BroadcastMessage. Try it and see if it works
pythagorusAuthor Commented:
I tried using the const instead of the channel object and it seems to do the trick, though I'm not sure I understand what effect the marshalling has on this. It is presumably messing about with some reference count which I cannot see, because I was checking that the count was 0.
Bought This Question.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now