DDE.SetLink fails if running in a new thread

I'm trying to use DDE.SetLink within a new thread, but the call fails right away, while it works normally if I don't do it threaded. What is wrong?


function mIRCinfo(P: Pointer) : LongInt; stdcall;
var DDE: TDDEClientConv;
begin
  try
    DDE := TDDEClientConv.Create(nil);
    if DDE.SetLink(mIRCSet.Service, mIRCSet.Topic) then
    begin
     DDE.OpenLink;
     DDE.PokeData(mIRCSet.Topic, PChar(mIRCSet.Command));
     DDE.CloseLink;
    end
    else
      showmessage('fail');
  finally
    DDE.Free;
  end;
end;
 
 
 
Var    thr : THandle;
          thrID : DWORD;
 
   thr:= CreateThread(nil, 0, @mIRCinfo, nil, 0, thrID);

Open in new window

LVL 3
bryan7Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
2266180Connect With a Mentor Commented:
I figured it out after going thourgh dde sources. the dde manager is created at ddeman unit initializaiton. so, since the ddeman unit is using a global vairable as the manager, it is obviously not thread safe. no matter what you do using the actual dde implementation you will not be able to work out a correct and thread-safe solution.

try the attached code and see that it works.

you will either have to rewrite the dde implementation and make it thread safe or find some other delphi dde implementation on the net which is thread safe.
I made a small search myself but did not find anything.

btw, just in case you don't know: don't use vcl/UI stuff in threads without calling synchronize or you'll get errors. so I hope those showmessages are only there for testing purposes (even so, they are troublesome as you get nasty errors from time to time)
uses ddeman, ActiveX, ddeml;
 
function mIRCInfoThreaded(P : Pointer): LongInt; stdcall;
var DDE: TDDEClientConv;
begin
   ddeMgr := TDdeMgr.Create(Application);
   DDE := TDDEClientConv.Create(nil);
   try
    if DDE.SetLink('mIRC', 'COMMAND') then
     begin
       DDE.OpenLink;
       DDE.CloseLink;
       showmessage('thread: this works');
      end
      else showmessage('thread: Failed to stablish link with DDE: '+inttostr(DdeGetLastError(ddemgr.DdeInstId)));
   finally
     DDE.Free;
   end;
  result:=0;
end;

Open in new window

0
 
2266180Commented:
you need to call coinitialize and cofinalize when the thread starts, respectivly ends, from the created thread. in your case, use another try finally which will incorporate the 2 calls.
0
 
bryan7Author Commented:
it still fails
function mIRCInfoThreaded(P : Pointer): LongInt; stdcall;
var DDE: TDDEClientConv;
begin
 try
   CoInitialize(nil);
  try
    DDE := TDDEClientConv.Create(nil);
    if DDE.SetLink(mIRCIntoSet.Service, mIRCIntoSet.Topic) then
    begin
     DDE.OpenLink;
//     DDE.PokeData(mIRCIntoSet.Topic, PChar(mIRCIntoSet.Command));
     DDE.CloseLink;
    end
    else showmessage('Failed to stablish link with DDE');
  finally
    DDE.Free;
  end;
 finally
   CoUninitialize;
 end;
end;

Open in new window

0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
2266180Commented:
what about:
uses ..., ActiveX;
 
....
 
function mIRCInfoThreaded(P : Pointer): LongInt; stdcall;
var DDE: TDDEClientConv;
begin
 try
   CoInitializeEx(nil, 0);
  try
    DDE := TDDEClientConv.Create(nil);
    if DDE.SetLink(mIRCIntoSet.Service, mIRCIntoSet.Topic) then
    begin
     DDE.OpenLink;
//     DDE.PokeData(mIRCIntoSet.Topic, PChar(mIRCIntoSet.Command));
     DDE.CloseLink;
    end
    else showmessage('Failed to stablish link with DDE');
  finally
    DDE.Free;
  end;
 finally
   CoUninitialize;
 end;
end;

Open in new window

0
 
bryan7Author Commented:
Same result, SetLink fails.
0
 
2266180Commented:
can you post a zip with a small demo which has this behaviour so I have something to work with?
thanks
0
 
bryan7Author Commented:
Open a new project, and simple paste the 2 functions and the code on form create:

You'll have to enable DDE in mirc, in Options, Other, DDE, "Enable DDE Server"

Then oncreate, you'll the non-threaded one works, and the other one fails.
unit Unit5;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ActiveX, ddeman;
 
type
  TForm5 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form5: TForm5;
 
implementation
 
{$R *.dfm}
 
function mIRCInfoThreaded(P : Pointer): LongInt; stdcall;
var DDE: TDDEClientConv;
begin
 try
   CoInitializeEx(nil, 0);
  try
    DDE := TDDEClientConv.Create(nil);
    if DDE.SetLink('mIRC', 'COMMAND') then
    begin
     DDE.OpenLink;
     DDE.CloseLink;
     showmessage('thread: this works');
    end
    else showmessage('thread: Failed to stablish link with DDE');
  finally
    DDE.Free;
  end;
 finally
   CoUninitialize;
 end;
end;
 
procedure mIRCInfoNotThreaded;
var DDE: TDDEClientConv;
begin
  try
    DDE := TDDEClientConv.Create(nil);
    if DDE.SetLink('mIRC', 'COMMAND') then
    begin
     DDE.OpenLink;
     DDE.CloseLink;
     showmessage('no thread: this works');
    end
    else showmessage('no thread: Failed to stablish link with DDE');
  finally
    DDE.Free;
  end;
end;
 
procedure TForm5.FormCreate(Sender: TObject);
Var thr : THandle;
    thrID : DWORD;
begin
  thr:= CreateThread(nil, 0, @mIRCinfoThreaded, nil, 0, thrID);
  mIRCInfoNotThreaded;
end;
 
end.

Open in new window

0
 
bryan7Author Commented:
Typo: "you'll see". How come there is no edit function ;(
0
 
bryan7Author Commented:
I see. Guess I'll just leave it be then and use the old way. Thanks!
0
 
2266180Commented:
B grade? I solve your problem correctly, give you alternative solutions, and you give me a B grade? Guess you didn't read the FAQ and help section not to mention the grading tips.

no problem, you just made it on my blacklist which basically means that I will no longer answer any of your questions.

no need to anwser as I've unsubscribed.

enjoy.
0
 
bryan7Author Commented:
I doubled the points instead so you got more points than you would otherwise with the original points*A
0
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.

All Courses

From novice to tech pro — start learning today.