Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

DDE.SetLink fails if running in a new thread

Posted on 2008-06-10
11
Medium Priority
?
888 Views
Last Modified: 2011-02-26
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
Comment
Question by:bryan7
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
11 Comments
 
LVL 28

Expert Comment

by:2266180
ID: 21749644
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
 
LVL 3

Author Comment

by:bryan7
ID: 21749770
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
 
LVL 28

Expert Comment

by:2266180
ID: 21749919
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 3

Author Comment

by:bryan7
ID: 21749971
Same result, SetLink fails.
0
 
LVL 28

Expert Comment

by:2266180
ID: 21750230
can you post a zip with a small demo which has this behaviour so I have something to work with?
thanks
0
 
LVL 3

Author Comment

by:bryan7
ID: 21750439
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
 
LVL 3

Author Comment

by:bryan7
ID: 21750450
Typo: "you'll see". How come there is no edit function ;(
0
 
LVL 28

Accepted Solution

by:
2266180 earned 300 total points
ID: 21751842
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
 
LVL 3

Author Closing Comment

by:bryan7
ID: 31465659
I see. Guess I'll just leave it be then and use the old way. Thanks!
0
 
LVL 28

Expert Comment

by:2266180
ID: 21752130
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
 
LVL 3

Author Comment

by:bryan7
ID: 21752244
I doubled the points instead so you got more points than you would otherwise with the original points*A
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Suggested Courses

604 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question