[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 910
  • Last Modified:

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

0
bryan7
Asked:
bryan7
  • 6
  • 5
1 Solution
 
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
 
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
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.

 
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
 
2266180Commented:
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
 
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

Featured Post

Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

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