我一直试图将这个错误弄清楚我们大约4天了。我正在使用Delphi XE并为翻译人员创建了一个小工具。我想到了使用Microsoft Translation API来帮助简化事情并且不那么繁琐。
我创建了一个访问Microsoft转换器API的类,但我想让它成为线程安全的,因此请求可以在后台进行。我发送获取访问令牌的请求没有问题,但是,我在一个单独的线程中运行该请求。当用户单击按钮时,我会生成一个新线程并运行http请求以从中转换术语。但是,它每次都会超时。如果我从同一个线程运行它没有问题。
以下是我用于发送http请求的方法(传递的THttpCli对象在线程之间共享)
function sendHTTPRequest(APost: Boolean; AURI: UTF8string;
AContentType: UTF8string; APostData: UTF8String; AHttpCli: TSSLHttpCli): UTF8string;
var
DataOut: TMemoryStream;
DataIn: TMemoryStream;
lHTMLStream: TStringStream;
lencoding: TUTF8Encoding;
lownClient: boolean;
begin
lownClient := false;
if AHttpCli = nil then
begin
AHttpCli := TSSLHttpCli.Create(nil);
AHttpCli.SslContext := TSSLContext.Create(nil);
with AHttpCli.SslContext do
begin
SSLCipherList := 'ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH';
SSLVersionMethod := sslV23_CLIENT;
SSLVerifyPeerModes := [SslVerifyMode_PEER]
end;
AHttpCli.MultiThreaded := true;
lownClient := true;
end;
AHttpCli.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
if APost then
begin
DataOut := TMemoryStream.Create;
DataOut.Write(APostData[1], Length(APostData));
DataOut.Seek(0, soFromBeginning);
end;
AHttpCli.URL := AURI;
AHttpCli.ContentTypePost := AContentType;
DataIn := TMemoryStream.Create;
if APost then AHttpCli.SendStream := DataOut;
AHttpCli.RcvdStream := DataIn;
try
if apost then
AHttpCli.Post
else
AHttpCli.Get;
lHTMLStream := TStringStream.Create('', TEncoding.UTF8);
lHtmlStream.LoadFromStream(AHttpCli.RcvdStream);
result := lHtmlStream.DataString;
lHtmlStream.Free;
finally
AHttpCli.Close;
AHttpCli.RcvdStream := nil;
AHttpCli.SendStream := nil;
DataIn.Free;
if APost then
DataOut.Free;
if lownClient then
AHttpCli.free;
end;
end;
我认为显而易见的解决方案是只有一个线程等待信号执行,但我希望能够解释为什么超时发生。我无法解释为什么第二个线程超时而第一个没有。
HTTP组件似乎卡在了dnslookup上。 OverbyteICS使用Windows函数WSAAsyncGetHostByName
来查找名称。
非常感谢任何帮助
因此,事实证明,在线程之间共享THttpCli
对象似乎是导致超时的原因。解决方案只是将nil
传递给我上面函数中的AHttpCli
参数。
我仍会接受一个答案,说明为什么会导致超时。据我所知,WSAAsyncGetHostByName
方法不使用任何同步对象而另一个线程没有同时运行,所以不应该阻塞线程。