Delphi: 如何从 idHTTPServer.OnCommandGet 方法在主线程中执行过程
Delphi: how to execute procedure in main thread from idHTTPServer.OnCommandGet method
我必须在我们的应用程序中创建一个嵌入式 HTTP 服务器。
进程间通信必须创建这个,因为对方只能调用WebService。
我们不需要一次处理更多请求,但我必须从主线程使用库和数据库连接。
Delphi版本是 Seattle,Indy 版本是 10(内部)。
据我所知,IdHTTPServer 像以前一样使用线程进行连接。
但是新的事件处理程序不直接传递 Thread - 所以我不能像 N 年前那样调用 TThread.Synchronize。
而且我没有找到任何获取线程的方法。
我在某处读到 TIdSync 或 TIdNotify 类 可以帮助我。我找不到任何完整的示例来了解如何操作。
看到这个简单的代码。在主线程中完成我的工作是否足够?
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
FURI := ARequestInfo.URI; // Store the URI for main thread access
FResult := '';
TIdSync.SynchronizeMethod(Self.ProcessIt); // Call sync to process in VCL thread
AResponseInfo.ContentText := FResult; // This variable contains the result
end;
还是我做错了什么?
感谢您的帮助!
dd
有一种方法可以访问 TIdContext
背后的底层 TThread
- 将 TIdContext.Yarn
属性 类型转换为 TIdYarnOfThread
然后访问其Thread
属性, 如:
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
Thread: TThread;
begin
Thread := (AContext.Yarn as TIdYarnOfThread).Thread;
FURI := ARequestInfo.URI;
FResult := '';
Thread.Synchronize(ProcessIt);
AResponseInfo.ContentText := FResult;
end;
但是,在你的情况下你实际上并不需要它,因为 TThread.Synchronize()
(and TThread.Queue()
) 有 class
方法重载,所以你不需要 TThread
对象来调用它,例如:
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
FURI := ARequestInfo.URI;
FResult := '';
TThread.Synchronize(nil, ProcessIt);
AResponseInfo.ContentText := FResult;
end;
TIdSync
(和TIdNotify
)确实可以代替使用,你所拥有的是一个好的开始,它只需要再充实一点,以便访问你的FURI
和 FResult
变量也是同步的,以防您需要一次处理多个客户端连接,因此需要避免并发访问变量,例如:
type
TIdProcessItSync = class(TIdSync)
URI: string;
Content: string;
protected
procedure DoSynchronize; override;
end;
procedure TIdProcessItSync.DoSynchronize;
begin
Content := Form5.ProcessIt(URI);
end;
function TForm5.ProcessIt(const URI: string): String;
begin
Result := ...;
end;
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
Sync: TIdProcessItSync;
begin
Sync := TIdProcessItSync.Create;
try
Sync.URI := ARequestInfo.URI;
Sync.Synchronize;
AResponseInfo.ContentText := Sync.Content;
finally
Sync.Free;
end;
end;
也就是说,TIdSync
(和 TIdNotify
)已被弃用,取而代之的是支持 anonymous procedures 的 TThread
的 class
方法重载,例如:
function TForm5.ProcessIt(const URI: string): String;
begin
Result := ...;
end;
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
URI, Content: String;
begin
URI := ARequestInfo.URI;
TThread.Synchronize(nil,
procedure
begin
Content := ProcessIt(URI);
end
);
AResponseInfo.ContentText := Content;
end;
或者:
function TForm5.ProcessIt(const URI: string): String;
begin
Result := ...;
end;
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
TThread.Synchronize(nil,
procedure
begin
AResponseInfo.ContentText := ProcessIt(ARequestInfo.URI);
end
);
end;
我必须在我们的应用程序中创建一个嵌入式 HTTP 服务器。 进程间通信必须创建这个,因为对方只能调用WebService。
我们不需要一次处理更多请求,但我必须从主线程使用库和数据库连接。
Delphi版本是 Seattle,Indy 版本是 10(内部)。
据我所知,IdHTTPServer 像以前一样使用线程进行连接。 但是新的事件处理程序不直接传递 Thread - 所以我不能像 N 年前那样调用 TThread.Synchronize。 而且我没有找到任何获取线程的方法。
我在某处读到 TIdSync 或 TIdNotify 类 可以帮助我。我找不到任何完整的示例来了解如何操作。
看到这个简单的代码。在主线程中完成我的工作是否足够?
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
FURI := ARequestInfo.URI; // Store the URI for main thread access
FResult := '';
TIdSync.SynchronizeMethod(Self.ProcessIt); // Call sync to process in VCL thread
AResponseInfo.ContentText := FResult; // This variable contains the result
end;
还是我做错了什么?
感谢您的帮助!
dd
有一种方法可以访问 TIdContext
背后的底层 TThread
- 将 TIdContext.Yarn
属性 类型转换为 TIdYarnOfThread
然后访问其Thread
属性, 如:
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
Thread: TThread;
begin
Thread := (AContext.Yarn as TIdYarnOfThread).Thread;
FURI := ARequestInfo.URI;
FResult := '';
Thread.Synchronize(ProcessIt);
AResponseInfo.ContentText := FResult;
end;
但是,在你的情况下你实际上并不需要它,因为 TThread.Synchronize()
(and TThread.Queue()
) 有 class
方法重载,所以你不需要 TThread
对象来调用它,例如:
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
FURI := ARequestInfo.URI;
FResult := '';
TThread.Synchronize(nil, ProcessIt);
AResponseInfo.ContentText := FResult;
end;
TIdSync
(和TIdNotify
)确实可以代替使用,你所拥有的是一个好的开始,它只需要再充实一点,以便访问你的FURI
和 FResult
变量也是同步的,以防您需要一次处理多个客户端连接,因此需要避免并发访问变量,例如:
type
TIdProcessItSync = class(TIdSync)
URI: string;
Content: string;
protected
procedure DoSynchronize; override;
end;
procedure TIdProcessItSync.DoSynchronize;
begin
Content := Form5.ProcessIt(URI);
end;
function TForm5.ProcessIt(const URI: string): String;
begin
Result := ...;
end;
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
Sync: TIdProcessItSync;
begin
Sync := TIdProcessItSync.Create;
try
Sync.URI := ARequestInfo.URI;
Sync.Synchronize;
AResponseInfo.ContentText := Sync.Content;
finally
Sync.Free;
end;
end;
也就是说,TIdSync
(和 TIdNotify
)已被弃用,取而代之的是支持 anonymous procedures 的 TThread
的 class
方法重载,例如:
function TForm5.ProcessIt(const URI: string): String;
begin
Result := ...;
end;
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
URI, Content: String;
begin
URI := ARequestInfo.URI;
TThread.Synchronize(nil,
procedure
begin
Content := ProcessIt(URI);
end
);
AResponseInfo.ContentText := Content;
end;
或者:
function TForm5.ProcessIt(const URI: string): String;
begin
Result := ...;
end;
procedure TForm5.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
TThread.Synchronize(nil,
procedure
begin
AResponseInfo.ContentText := ProcessIt(ARequestInfo.URI);
end
);
end;