我从未在任何社区提问,因为我总是自己解决问题或者可以在网上找到问题。但是有了这个,我走到了死胡同,需要帮助! 为了清楚起见 - 我转换了一个简单的应用程序,在其他地方找到它以使其使用Tthread对象。 这个想法很简单 - 应用程序使用webservice在线检查,通过THTTPRIO组件,天气并将结果放入Memo1行。
点击Button1,我们以标准方式完成它 - 使用THTTPRIO放在Form1上(在这里称为原始app中的htt)并使用主线程和唯一线程。
procedure TForm1.Button1Click(Sender: TObject);
var
wf:WeatherForecasts;
res:ArrayOfWeatherData;
i:integer;
begin
wf:=(htt as WeatherForecastSoap).GetWeatherByPlaceName(edit1.Text);
if wf.PlaceName<> '' then
res:=wf.Details;
memo1.Lines.Add('The min and max temps in Fahrenheit is:');
memo1.Lines.Add(' ');
for i:= 0 to high(res) do
begin
memo1.Lines.Add(res[i].Day+' - '+ ' Max Temp. Fahr: '+res[i].MaxTemperatureF+' - '+'Min Temp Fahr: '+res[i].MinTemperatureF);
end
end;
点击Button2 - 我们使用类TThread
procedure TForm1.Button2Click(Sender: TObject);
var WFThread:WeatherThread;
begin
WFThread := WeatherThread.Create (True);
WFThread.FreeOnTerminate := True;
WFThread.Place := Edit1.Text;
WFThread.Resume;
end;
在WeatherThread1单元的执行过程中,我输入了以下代码:
procedure WeatherThread.Execute;
begin
{ Place thread code here }
GetForecast;
Synchronize (ShowWeather);
end;
...和GetForecast代码:
procedure WeatherThread.GetForecast;
var
HTTPRIO: THTTPRIO;
wf:WeatherForecasts;
res:ArrayOfWeatherData;
i:integer;
begin
HTTPRIO := THTTPRIO.Create(nil);
HTTPRIO.URL := 'http://www.webservicex.net/WeatherForecast.asmx';
HTTPRIO.WSDLLocation := 'http://www.webservicex.net/WeatherForecast.asmx?WSDL';
HTTPRIO.Service := 'WeatherForecast';
HTTPRIO.Port := 'WeatherForecastSoap';
wf:=(HTTPRIO as WeatherForecastSoap).GetWeatherByPlaceName(Place);
if Lines=nil then Lines:=TStringList.Create;
if wf.PlaceName<> '' then
res:=wf.Details;
Lines.Clear;
for i:= 0 to high(res) do
begin
Lines.Add(res[i].Day+' - '+ ' Max Temp. Fahr: '+res[i].MaxTemperatureF+' - '+'Min Temp Fahr: '+res[i].MinTemperatureF);
end;
end;
过程ShowWeather在Form1.Memo1中显示结果。 现在有一个问题:在主线程中,单击Button1,一切正常。但当然,当HTTPRIO组件进行通信时 - 它会冻结表单。
使用Button2我将代码放在单独的线程中,但它不想工作!奇怪的事发生了。当我启动应用程序 - 并单击Button2时,使用HTTPRIO组件时出错。但是当我点击第一个Button1和AFTER THAT Button2时它会工作一段时间(但是它可以工作一段时间,只有5-7次点击)。 我想我做错了但却无法弄清楚问题出在哪里以及如何解决问题。看起来线程单元中的代码不是线程安全的,但它应该是。请帮助如何使HTTPRIO在线程中工作!!!
您可以找到压缩的完整代码here。
答案 0 :(得分:4)
当我在Delphi 2007中运行代码时,madExcept显示异常未调用CoInitialize。
在execute方法中添加对CoInitialize的调用后,将调用webservice而不会出现问题。
可能的解决方法
procedure TWeatherThread.Execute;
begin
CoInitialize(nil);
try
...
finally
CoUninitialize;
end;
end;
答案 1 :(得分:1)
远景,但我在这里缺少对Synchronize的调用:
您永远不应该直接从线程代码更新GUI。
您应该将这些调用嵌入到方法中,然后使用TThread.Synchronize method调用该方法。
Delphi有一个nice demo on this
从Delphi 4开始,它在sortthds.pas
子目录中包含了一个名为...\demos\threads
的演示,显示了相同的内容。
- 的Jeroen
答案 2 :(得分:0)
通过动态创建RIO(RIO对象具有奇怪的生命周期)和线程化,并将结果与简单的Button1进行比较,可能会使问题蒙上阴影。我做了另一个没有线程调用GetForecast的按钮。看看是否有效。如果它轰炸,那么你的问题就不是线程。