怎样异步连接SocketConnection? 连接时可以同时进行其它工作(100分)

  • 主题发起人 主题发起人 LiChaoHui
  • 开始时间 开始时间
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
我建立了一个连接线程,在线程中连接,连接倒是成功了,
可是建立的这个连接在主线程中不能使用,总是报告错误“必须加载一个DLL。”
有谁做有成功的例子?
 
請找到midas.dll文件在命令行執行
regedit midas.dll即可.
 
regedit midas.dll或直是tregsvr MIDAS.DLL
 
楼上可能没有明白我的意思,我是说在线程中连接应用服务器,连接成功后,
在主线程中使用此连接
 
不知道楼主设计这个线程是不是为了防止SocketConnection在第一次连接时因为连接时间过长从而阻塞了主程序的运行?如果是这样可以把主线程的SocketConnection在线程Create时传到线程中去。以下是我曾经写过的一个简单的办法,用来防止第一次远程调用COM+时时间过长而客户端不能操作的情况,你可以参考一下:
.............
.............
TQueryThread=Class(TThread)
private
FCDSAuthors:TClientDataSet;
FCDSBooks:TClientDataSet;
FObjQuery:variant;//Com+对象
FAuthorsData:OleVariant;
FBooksData:OleVariant;
FStatusBar:TStatusBar;
FStr:string;//状态提示
protected
procedure Execute;override;
procedure UpdateCDS;
procedure UpdateSBar;//显示目前状态
public
//这儿传入主线程中的VCL
constructor Create(CDS1,CDS2:TClientDataSet;SBar:TStatusBar);
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
const
MachineName:string='机器名';
var
hMutex:THandle=0;//互拆对象
constructor TQueryThread.Create(CDS1,CDS2:TClientDataSet;SBar:TStatusBar);
begin
FreeOnTerminate:=True;
FCDSAuthors:=CDS1;
FCDSBooks:=CDS2;
FStatusBar:=SBar;
inherited Create(False);
end;

procedure TQueryThread.Execute;
begin
if WaitForSingleObject(hMutex,0)=WAIT_OBJECT_0 then
begin
CoInitialize(nil);
FStr:='正在连接并获取数据........................';
try
try
//application.initialize;
Synchronize(UpdateSBar);
FObjQuery:=CoXTQuery.CreateRemote(MachineName);//这步需要较长时间,类似SocketConnection的连接
FObjQuery.GetAuthors_ForGUI('select * from authors',FAuthorsData);
FObjQuery.GetBooks_ForGUI('select * from Books',FBooksData);
FObjQuery:=null;
Synchronize(UpdateCDS);
FStr:='结束';
except
on Exceptiondo
FStr:='获取数据失败';
end;
finally
Synchronize(UpdateSBar);
CoUninitialize;
ReleaseMutex(hMutex);
end;
end;
end;

procedure TQueryThread.UpdateCDS ;
begin
try
FCDSAuthors.Data:=FAuthorsData;
FCDSBooks.Data:=FBooksData;
except
on Exceptiondo
showmessage('数据错误');
end;
end;

procedure TQueryThread.UpdateSBar;
begin
FStatusBar.Panels[0].Text:=FStr;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
hMutex:=CreateMutex(nil,False,nil);
application.initialize;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hMutex);
end;

//连接并获得数据
procedure TForm1.btnGetDataClick(Sender: TObject);
begin
TQueryThread.Create(CDSAuthors,CDSBooks,StatusBar1);
end;
 
我说的是两个线程能轮流的使用一个连接吗?
一个线程建立的连接,不知道为什么不能被主线程使用
 
to LiChaoHui:接口没Marshal吧.
http://www.thedelphimagazine.com/samples/comthread/comthreading.htm
 
呵呵,不太懂啊
 
能不能把你的代码贴出来?我们好知道你到底想实现什么?
其实我上面的代码就是实现用线成建立连接并传入数据到ClientDataSet(这个过程也可以类似你的SocketConnection建立连接),其他线程当然也可以使用这个连接,只要也把主线程创建的SocketConnection传进去就行了,只不过在改变属性的时候要注意同步。
 
我知道DCOM连接是可以支持多线程的,但是SocketConnection似乎不行
我的代码如下,我的目的是,在用户输入工号和口令的同时,
程序在后台完成连接和一些初始化操作,让程序看起来启动的更快些
procedure TForm1.Button3Click(Sender: TObject);
begin
SocketConnection1.Connected := False;
if Assigned(ct) then
FreeAndNil(ct);
ct := TConThread.Create(True);
ct.Conn := SocketConnection1;
ct.Resume;
end;

TConThread = class(TThread)
protected
procedure Execute;
override;
public
Conn: TSocketConnection;
ok: Boolean;
err: Boolean;
end;

{ TConThread }
procedure TConThread.Execute;
begin
CoInitialize(nil);
try
ok := False;
Conn.Connected := True;
ok := True;
except
err := True;
end;
CoUninitialize;
end;

然后前台定时检测后台线程是否完成连接,
如果完成,则使用此连接,但是使用时出错
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Tag := Timer1.Tag + 1;
if Assigned(ct) then
begin
if ct.err then
Caption := 'error' else
if ct.ok then
Caption := 'ok' + ' ' + IntToStr(Timer1.Tag)
else
Caption := '..' + ' ' + IntToStr(Timer1.Tag)
end
else
caption := 'unknow';
end;
 
在那里出错了?
是不是调用DCOM对象上的方法出错了
 
这里出错了,在主线程中取数据时出错了
procedure TForm1.Button1Click(Sender: TObject);
var
t1, t2: Integer;
begin
t1 := GetTickCount;
if not ClientDataSet1.Active then
begin
ClientDataSet1.RemoteServer := nil;
ClientDataSet1.RemoteServer := SocketConnection1;
end;
//此行出错
ClientDataSet1.Active := not ClientDataSet1.Active;
t2 := GetTickCount;
ShowMessage('use time: ' + IntToStr(t2-t1) + 's');
end;
 
[blue] Conn.Connected := True;[/blue]
这句话意味着远程数据模块的建立,即DCom对象的建立,而且别忘了
这对象是在你的ct线程建立的;
[red]ClientDataSet1.Active := not ClientDataSet1.Active;[/red]
这句意味着你要调用DCom对象上IAppserver的 AS_GetRecords 方法.
这样你从另一个线程中调用了接口上的方法,这在Com中是不不行的,需要打包(Marshal),非常麻烦.为什么就可以看我上面连接的那篇文章。
所以看来异步连接SocketConnection是不行的-(
 
呵呵,没关系,即使没有结果,也学到了不少的东西
 
有意思,如果SocketConnection不能这样异步实现,我想客户肯定是不会满意这种连接速度的。我等下去试试,看看能不能有好的解决办法。或者只能Marshal接口了....
 
to xiaasp,
太好了,我就是感觉用拨号连接时,连接的速度太慢,
所以才使用线程的,
但是,分析了一下Delphi自己的代码,感觉到SocketConnection
好像本身已经使用了你所说的那种Marshal的方法了
等你的好消息, 看有没有一种理想的方法,修改SConnect.pas也行的
 
不行了,有点晕了,看看这个能不能有帮助吧
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1470623
 
多人接受答案了。
 
后退
顶部