客户端在线程中调用服务器的Web Service出现异常 ( 积分: 100 )

  • 主题发起人 主题发起人 bbser
  • 开始时间 开始时间
B

bbser

Unregistered / Unconfirmed
GUEST, unregistred user!
用Delphi7写了一个很简单的客户端,用于获取服务器产生的随机数,并使用其自带的 WSDL Importer 导入了服务器端的 Web Service,在主VCL线程中一切正常,但是如果将代码放入线程执行,则报出异常:Class EOleSysError with message "尚未调用CoInitionalize"。查了很多资料不知道如何解决,请高手指点。该Web Service目前可用,高手可以进行测试。源码如下:
主程序:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
edtRandom: TEdit;
btnGetRandom: TButton;
procedure btnGetRandomClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
uses MagicService, ThrdGetRand;
{$R *.dfm}
procedure TForm1.btnGetRandomClick(Sender: TObject);
var
Thrd:TThrdGetRandom;
begin
Thrd:=TThrdGetRandom.Create(True);
Thrd.FreeOnTerminate:=True;
Thrd.Resume;
end;
end.

线程:
unit ThrdGetRand;
interface
uses
Classes;
type
TThrdGetRandom = class(TThread)
private
FRandom: AnsiString;
procedure DispRandom;
protected
procedure Execute;
override;
end;

implementation
uses MagicService, main;
procedure TThrdGetRandom.Execute;
begin
FRandom:=GetMagicServiceSoap.GetRand('pppp');
Synchronize(DispRandom);
end;

procedure TThrdGetRandom.DispRandom;
begin
Form1.edtRandom.Text:=FRandom;
end;
end.

Web Service文件:
unit MagicService;
interface
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
type
MagicServiceSoap = interface(IInvokable)
['{E04062C9-6555-17A8-EC63-780D5C2FFD89}']
function GetRand(const userName: WideString): WideString;
stdcall;
end;

function GetMagicServiceSoap(UseWSDL: Boolean=System.False;
Addr: string='';
HTTPRIO: THTTPRIO = nil): MagicServiceSoap;
implementation
function GetMagicServiceSoap(UseWSDL: Boolean;
Addr: string;
HTTPRIO: THTTPRIO): MagicServiceSoap;
const
defWSDL = 'http://202.196.64.86/service/MagicService.asmx?wsdl';
defURL = 'http://202.196.64.86/service/MagicService.asmx';
defSvc = 'MagicService';
defPrt = 'MagicServiceSoap';
var
RIO: THTTPRIO;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := THTTPRIO.Create(nil)
else
RIO := HTTPRIO;
try
Result := (RIO as MagicServiceSoap);
if UseWSDL then
begin
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
end else
RIO.URL := Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end;
end;

initialization
InvRegistry.RegisterInterface(TypeInfo(MagicServiceSoap), 'http://tempuri.org/', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(MagicServiceSoap), 'http://tempuri.org/%operationName%');
InvRegistry.RegisterInvokeOptions(TypeInfo(MagicServiceSoap), ioDocument);
end.
 
用Delphi7写了一个很简单的客户端,用于获取服务器产生的随机数,并使用其自带的 WSDL Importer 导入了服务器端的 Web Service,在主VCL线程中一切正常,但是如果将代码放入线程执行,则报出异常:Class EOleSysError with message "尚未调用CoInitionalize"。查了很多资料不知道如何解决,请高手指点。该Web Service目前可用,高手可以进行测试。源码如下:
主程序:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
edtRandom: TEdit;
btnGetRandom: TButton;
procedure btnGetRandomClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
uses MagicService, ThrdGetRand;
{$R *.dfm}
procedure TForm1.btnGetRandomClick(Sender: TObject);
var
Thrd:TThrdGetRandom;
begin
Thrd:=TThrdGetRandom.Create(True);
Thrd.FreeOnTerminate:=True;
Thrd.Resume;
end;
end.

线程:
unit ThrdGetRand;
interface
uses
Classes;
type
TThrdGetRandom = class(TThread)
private
FRandom: AnsiString;
procedure DispRandom;
protected
procedure Execute;
override;
end;

implementation
uses MagicService, main;
procedure TThrdGetRandom.Execute;
begin
FRandom:=GetMagicServiceSoap.GetRand('pppp');
Synchronize(DispRandom);
end;

procedure TThrdGetRandom.DispRandom;
begin
Form1.edtRandom.Text:=FRandom;
end;
end.

Web Service文件:
unit MagicService;
interface
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
type
MagicServiceSoap = interface(IInvokable)
['{E04062C9-6555-17A8-EC63-780D5C2FFD89}']
function GetRand(const userName: WideString): WideString;
stdcall;
end;

function GetMagicServiceSoap(UseWSDL: Boolean=System.False;
Addr: string='';
HTTPRIO: THTTPRIO = nil): MagicServiceSoap;
implementation
function GetMagicServiceSoap(UseWSDL: Boolean;
Addr: string;
HTTPRIO: THTTPRIO): MagicServiceSoap;
const
defWSDL = 'http://202.196.64.86/service/MagicService.asmx?wsdl';
defURL = 'http://202.196.64.86/service/MagicService.asmx';
defSvc = 'MagicService';
defPrt = 'MagicServiceSoap';
var
RIO: THTTPRIO;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := THTTPRIO.Create(nil)
else
RIO := HTTPRIO;
try
Result := (RIO as MagicServiceSoap);
if UseWSDL then
begin
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
end else
RIO.URL := Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end;
end;

initialization
InvRegistry.RegisterInterface(TypeInfo(MagicServiceSoap), 'http://tempuri.org/', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(MagicServiceSoap), 'http://tempuri.org/%operationName%');
InvRegistry.RegisterInvokeOptions(TypeInfo(MagicServiceSoap), ioDocument);
end.
 
把FRandom:=GetMagicServiceSoap.GetRand('pppp');
也放在DispRandom过程中,
 
由于调用Web Service是一个耗时的操作,如果放在主VCL中执行,客户端界面会有一段时间失去响应。因此,我才希望将调用放在子线程中执行,子线程在调用Web Service的时候不要与主VCL线程进行同步。否则就达不到多线程的效果了
 
你重载线程的Create,把FRandom:=GetMagicServiceSoap.GetRand('pppp');
放在Create执行.
 
我已经按照你的方法试过了,达不到多线程的目的,主界面一样会出现停滞现象。你可能还没有明白我到底想完成什么,我是希望执行Web Service时不要占用主VCL线程。重载Create不是跟Synchronize一样的吗!!!
 
uses ActiveX;
initialization
CoInitialize(Nil);
finalization
CoUnInitialize;
 
同意xianguo,在线程文件中要先初始化com库才能调用webservice的
 
后退
顶部