【发布时间】:2010-08-08 19:28:34
【问题描述】:
我从来没有在任何社区提出过问题,因为我总是自己解决问题或者可以在网上找到问题。但是有了这个,我走到了死胡同,需要帮助! 说得非常清楚——我转换了一个简单的应用程序,在别处找到使它使用 Tthread 对象。 这个想法很简单——应用程序使用 web 服务在线检查,通过 THTTPRIO 组件,天气并将结果放在 Memo1 行中。
单击 Button1,我们以标准方式完成它 - 使用 Form1 上的 THTTPRIO(在原始应用程序中称为 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;
Procedure ShowWeather 在 Form1.Memo1 中显示结果。 现在有一个问题:在主线程中,单击 Button1,一切正常。当然,当 HTTPRIO 组件进行通信时,它会冻结表单。
使用 Button2,我将代码放在单独的线程中,但它不想工作!奇怪的事情发生了。当我启动应用程序并单击 Button2 时,使用 HTTPRIO 组件时出现错误。但是当我点击 FIRST Button1 和 AFTER Button2 时它可以工作一段时间(但它可以工作一段时间,只点击 5-7 次)。 我想我做错了什么,但无法弄清楚问题出在哪里以及如何解决。看起来线程单元中的代码不是线程安全的,但它应该是。请帮助如何使 HTTPRIO 在线程中工作!!!
您可以找到压缩后的完整代码here。
【问题讨论】:
-
当您说某事“奇怪”并且发生“错误”时,您需要更加具体。什么错误?
-
您确实意识到您的 WeatherTread.GetForecast 中存在内存泄漏?您创建但从未释放 THTTPRIO 实例。
-
这不是真的,@Marjan。在没有所有者的情况下创建 THTTPRIO 时,它使用接口引用计数来管理其生命周期。将其类型转换为 WeatherForecastSoap 会创建一个临时接口引用,该引用会在函数结束时释放。
-
所有的线程代码都在这里了吗?我没有看到对
CoInitialize的呼叫。 Delphi 在为主线程初始化“ComObj.pas”时处理调用,但对于单独的线程,您可以自己调用它。顺便说一句,你在代理后面吗? -
@Rob Kennedy:感谢您澄清这一点。我猜我是从臀部射击......
标签: delphi thread-safety webservice-client tthread