3

我从来没有在任何社区问过问题,因为我总是自己解决问题或者可以在网上找到问题。但是有了这个,我走到了死胡同,需要帮助!说得很清楚——我转换了一个简单的应用程序,在别处找到,使它使用 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;

过程 ShowWeather 在 Form1.Memo1 中显示结果。现在有一个问题:在主线程中,单击 Button1,一切正常。当然,当 HTTPRIO 组件进行通信时,它会冻结表单。

使用 Button2,我将代码放在单独的线程中,但它不想工作!奇怪的事情发生了。当我启动应用程序并单击 Button2 时,使用 HTTPRIO 组件时出现错误。但是当我点击 FIRST Button1 和 AFTER Button2 时它可以工作一段时间(但它可以工作一段时间,只点击 5-7 次)。我想我做错了什么,但无法弄清楚问题出在哪里以及如何解决它。看起来线程单元中的代码不是线程安全的,但它应该是。请帮助如何使 HTTPRIO 在线程中工作!!!

您可以在此处找到压缩后的完整代码。

4

3 回答 3

4

当我在 Delphi 2007 中运行您的代码时,madExcept 显示未调用 异常CoInitialize。
在执行方法中添加对 CoInitialize 的调用后,webservice 被调用没有问题。

可能的修复

procedure TWeatherThread.Execute;
begin
  CoInitialize(nil);
  try
     ...
  finally
    CoUninitialize;
  end;
end;
于 2010-08-09T09:31:26.707 回答
1

远射,但我在这里错过了对同步的调用:

你永远不应该直接从你的线程代码更新你的 GUI。

您应该将这些调用嵌入到一个方法中,并为此使用TThread.Synchronize 方法调用该方法。

Delphi about 对此有一个很好的演示
从 Delphi 4 开始,它包含一个sortthds.pas...\demos\threads子目录中调用的演示,显示相同。

——杰伦

于 2010-08-09T10:22:49.457 回答
0

您可能会通过创建动态 RIO(RIO 对象具有奇怪的生命周期)并将该结果与简单的 Button1 进行比较,从而使问题变得模糊不清。我会制作另一个没有线程调用 GetForecast 的按钮。看看这是否有效。如果它爆炸了,那么你的问题不是线程。

于 2010-08-08T20:26:37.120 回答