三层结构,客户端多线程(100分)

  • 主题发起人 chengjian
  • 开始时间
C

chengjian

Unregistered / Unconfirmed
GUEST, unregistred user!
我在写一个三层结构的程序。
应用服务也是DELPHI 的,用的是RemoteDataModule。
客户端是一个多线程的程序,我的客户端线程中调用DCOMCONNEBT 时出错,
在主进程中调用时,没有问题,好象只能用单线程的。还是我有哪个地方没有
注意到?
有没有人写过类似结构的程序,请指教!
 
再说清楚一些:
应用服务器在一台机器上,与WEB服务器,数据库服务器及许多工作站相联。
网络用户在WEB上进行查询,增删数据。
本地用在工作站上通过前端程序(多线程)进行查询,增删数据。
系统的数据量比较少。
在前端程序多线程中:
在主线程中调用接口时,如果应用服务器与数据库联接断开,系统就死了。
在线程中调用接口时,系统提示‘没有引用的存储对象’,这个错误是因为线程同步产生的
如果用线程同步(都在在线程中调用)的话,那么,多线程失去了意义。
我该怎么做?
另外,在WEB中调用DCOM好象也用问题,但CORBA我又一点都不会,真是.....
老板月底要交货.....
 
[red]每个线程要对应一个DCOMCONNETION。[/red]否则失去多线程的意义。
可以动态创;如果知道线程的数量的话,也可以在设计期间就创建好。
另外要记得在线程中先调用CoInitialize初始化com环境,调用完毕后用
CoUninitialize结束.
 
TO: Xeen
是的。线程中动态创DCOMCONNETION是可以的。如果线程执行过程中发生了异常,
DCOMCONNETION就无法FREE。有没有其它的办法?
 
用try
......
finally
......
end;
发生异常后资源也能得到正确释放.
 
每一个线程要一个Tssesion
 
程序如下:
线程CREATRE
CREATE DCOMCONNETION
线程Destroy
DCOMCONNETION.FREE

线程执行
DCOMConnection.AppServer.FUN1
if a then

begin
DCOMConnection.AppServer.FUNC2
WRITELONG()
END
else
begin
DCOMConnection.AppServer.FUNC3
WRITELONG()
END
DCOMConnection.AppServer.FUNC4
WRITELONG()
如何做?
另外,多线程在WRITELONG时,也有问题
WRITELONG:是写文本文件。



 
unit Unit2;
interface
uses
Classes,mconnect,comobj,activex,IdGlobal;
type
TClientThread = class(TThread)
private
{ Private declarations }
mydcom :tdcomconnection;
protected
procedure Execute;
override;
end;

implementation
{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TClientThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ TClientThread }
procedure TClientThread.Execute;
begin
try
CoInitialize(0);
mydcom := tdcomconnection.Create(nil);
初始化mydcom的参数.....
执行应用服务器的方法.....
.......
finally
freeandnil(mydcom);
CoUninitialize;
end;
end;

end.

如果要在线程执行写文件等要独占资源的操作,可以用临界区,
互斥员等来同步线程.
 
unit MyTaxPhoneUnit;
interface
uses
windows, messages,Classes, DMFAXLib_TLB, SysUtils, Dialogs,MConnect,ActiveX;
type
TMyTaxPhone = class(TThread)
private
MyChannelsNo: integer;
MyDMFax: TDMFAX;
MyDCOMConnection:TDCOMConnection;
MyMainHandle: Thandle;
MyResult:integer;
TaxNo:string;
AccountNo:string;
Password:string;
NewPassword:string;
protected
procedure Execute;
override;
procedure PlayMoney(MyMoney:do
uble);
procedure PlayDate(MyDate: Tdatetime);
procedure PlayTime(MyTime: Tdatetime);
procedure PlayInteger(MyInteger: Integer);
function AccountNoAndPass(): integer;
function InputDate(): integer;
function IsBusyDate(): Boolean;
function PlayVoc(VocCode: string;
KeyDownStop: integer): integer;
function PlayVocGetDTFM(VocCode: string;
KeyDownStop: integer;
KeyConform: Boolean;
var MyDTFM: string): integer;
public
constructor Create(MainHandle: Thandle;
DMFax: TDMFAX;
ChannelsNo: integer);
destructor Destroy;
override;
end;

implementation
uses TelTaxPublicUnit;
constructor TMyTaxPhone.Create(MainHandle: Thandle;
DMFax: TDMFAX;
ChannelsNo: integer);
begin
MyChannelsNo := ChannelsNo;
MyDMFax := DMFax;
MyMainHandle := MainHandle;
MyDCOMConnection := TDCOMConnection.Create(Nil);
MyDCOMConnection.ServerName := 'TaxServer.Mypooler';
MyDCOMConnection.ComputerName := 'Lcg';
MyDCOMConnection.Connected := False;
inherited Create(FALSE);
end;

destructor TMyTaxPhone.Destroy;
begin
MyDCOMConnection.Connected := False;
MyDCOMConnection.Free;
inherited Destroy;
end;

procedure TMyTaxPhone.Execute;
label
MainSelect, TaxDeclare, ChangePass, TaxQuery, ExitStep, DeclareQuery;
label
OrganIntroduce, TaxIntroduce, TaxKnowledge,
TaxKnowledgeTax, TaxKnowledgeAdd;
var
ReceptDTMF :string;
begin
FreeOnTerminate := True;
//第一步:播放欢迎词
SendMessage(MyMainHandle,CM_CHANNELSTATUS,MyChannelsNo,1);
if PlayVoc('Index50',0) = 3 then
goto ExitStep;
//第二步:播放最新通知
SendMessage(MyMainHandle,CM_CHANNELSTATUS,MyChannelsNo,2);
if PlayVoc('Index51',0) = 3 then
goto ExitStep;
MainSelect:
//第三步:提示输入选择功能,接收选择功能(1-报税,2-申报查询,3-更改密码,4-咨询)
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,3);
if PlayVocGetDTFM('Index52', 1, False,ReceptDTMF) = 3 then
goto ExitStep;
if ReceptDTMF = '1' then
goto TaxDeclare;
//税务申报
if ReceptDTMF = '2' then
goto DeclareQuery;
//税务申报查询
if ReceptDTMF = '3' then
goto ChangePass;
//更改密码
if ReceptDTMF = '4' then
goto TaxQuery //税务咨询
else
goto ExitStep;
//退出
TaxDeclare: //税务申报
//提示输入接收税号,密码
if AccountNoAndPass() <> 1 then
goto Exitstep;
//应申报的总金额
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,11);
PlayVoc('Index40', 0);
Sleep(1000);
//取税金,播放税金,
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,12);
PlayMoney(2342.00);
Sleep(1000);
//确认接收功能(0 -取消,1-确定)
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,13);
if PlayVocGetDTFM('Index44', 0, False, ReceptDTMF) = 3 then
goto ExitStep;
if ReceptDTMF = '1' then
begin
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,14);
//播放等待语,银行下帐
PlayVoc('Index34', 0);
Sleep(2000);
//播放下帐成功与否
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,16);
PlayVoc('Index67', 0);
//取凭证
PlayVoc('Index68', 0);
end else
begin
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,15);
PlayVoc('Index72', 0);
end;
Goto MainSelect;

function TMyTaxPhone.AccountNoAndPass(): integer;
var
ReceptDTMF:string;
IsValidNo :Boolean;
begin
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,4);
if PlayVocGetDTFM('Index45', 0, True, ReceptDTMF) = 3 then
begin
Result := 3;
exit;
end;
TaxNo := ReceptDTMF;
try
CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
MyDCOMConnection.Connected := True;
MyDCOMConnection.AppServer.CheckPassword(TaxNo,Password,AccountNo,MyResult);
MyDCOMConnection.Connected := False;
finally
CoUninitialize;
end;

if MyResult = 1 then
begin

end
else
if MyResult = 2 then
begin
//提示输入税号错误,重新输入
if PlayVocGetDTFM('Index48', 0, True, ReceptDTMF) = 3 then
begin
Result := 3;
exit;
end;
TaxNo := ReceptDTMF;
try
CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
MyDCOMConnection.Connected := True;
MyDCOMConnection.AppServer.CheckPassword(TaxNo,Password,AccountNo,MyResult);
MyDCOMConnection.Connected := False;
finally
CoUninitialize;
end;

if MyResult <> 0 then
begin
if PlayVocGetDTFM('Index48', 0, True, ReceptDTMF)= 3 then
begin
Result := 3;
exit;
end;
TaxNo := ReceptDTMF;
try
CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
MyDCOMConnection.Connected := True;
MyDCOMConnection.AppServer.CheckPassword(TaxNo,Password,AccountNo,MyResult);
MyDCOMConnection.Connected := False;
finally
CoUninitialize;
end;

if MyResult <> 0 then
begin
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,7);
PlayVoc('Index32', 0);
Result := 3;
exit;
end;
end;
end;

//判断是否是合法用税户
// Password := '123456';
IsValidNo := True;
if not IsValidNo then
begin
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,6);
PlayVoc('Index63',0);
Result := 3;
Exit;
end;

//提示输入密码,接收密码
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,5);
if PlayVocGetDTFM('Index46', 0, True, ReceptDTMF) = 3 then
begin
Result := 3;
exit;
end;
if ReceptDTMF <> PassWord then
begin
if PlayVocGetDTFM('Index47', 0, True, ReceptDTMF) = 3 then
begin
Result := 3;
exit;
end;
if ReceptDTMF <> PassWord then
begin
if PlayVocGetDTFM('Index47', 0, True, ReceptDTMF) = 3 then
begin
Result := 3;
exit;
end;
if ReceptDTMF <> PassWord then
begin
SendMessage(MyMainHandle, CM_CHANNELSTATUS,MyChannelsNo,7);
PlayVoc('Index32', 0);
Result := 3;
exit;
end;
end;
end;
Result := 1;
end;


end.
 

我再试试!
 
To 版主(Chenlili)
为什么我定了邮件通知,收不到邮件?
 
接受答案了.
 
顶部