【发布时间】:2012-05-13 10:45:14
【问题描述】:
我的 Delphi 2010 应用程序使用多线程上传内容,上传的数据被 POST 到需要登录的 PHP/Web 应用程序,所以我需要使用共享/全局 cookie 管理器(我正在使用 Indy10 Revision 4743 ) 因为 TIdCookieManager 不是线程安全的:(
此外,服务器端会话 ID 每 5 分钟自动重新生成一次,因此我必须保持全局和本地 cookie 管理器同步。
我的代码如下所示:
TUploadThread = class(TThread)
// ...
var
GlobalCookieManager : TIdCookieManager;
procedure TUploadThread.Upload(FileName : String);
var
IdHTTP : TIdHTTP;
TheSSL : TIdSSLIOHandlerSocketOpenSSL;
TheCompressor : TIdCompressorZLib;
TheCookieManager : TIdCookieManager;
AStream : TIdMultipartFormDataStream;
begin
ACookieManager := TIdCookieManager.Create(IdHTTP);
// Automatically sync cookies between local & global Cookie managers
@TheCookieManager.OnNewCookie := pPointer(Cardinal(pPointer( procedure(ASender : TObject; ACookie : TIdCookie; var VAccept : Boolean)
begin
OmniLock.Acquire;
try
GlobalCookieManager.CookieCollection.AddCookie(ACookie, TIdHTTP(TIdCookieManager(ASender).Owner).URL{IdHTTP.URL});
finally
OmniLock.Release;
end; // try/finally
VAccept := True;
end )^ ) + $0C)^;
// ======================================== //
IdHTTP := TIdHTTP.Create(nil);
with IdHTTP do
begin
HTTPOptions := [hoForceEncodeParams, hoNoParseMetaHTTPEquiv];
AllowCookies := True;
HandleRedirects := True;
ProtocolVersion := pv1_1;
IOHandler := TheSSL;
Compressor := TheCompressor;
CookieManager := TheCookieManager;
end; // with
OmniLock.Acquire;
try
// Load login info/cookies
TheCookieManager.CookieCollection.AddCookies(GlobalCookieManager.CookieCollection);
finally
OmniLock.Release;
end; // try/finally
AStream := TIdMultipartFormDataStream.Create;
with Stream.AddFile('file_name', FileName, 'application/octet-stream') do
begin
HeaderCharset := 'utf-8';
HeaderEncoding := '8';
end; // with
IdHTTP.Post('https://www.domain.com/post.php', AStream);
AStream.Free;
end;
但它不起作用!调用 AddCookies() 时出现此异常
Project MyEXE.exe 引发异常类 EAccessViolation 并显示消息 '地址 00000000 的访问冲突。读取地址 00000000'。
我也尝试过使用assign(),即。
TheCookieManager.CookieCollection.Assign(GlobalCookieManager.CookieCollection);
但我仍然遇到同样的异常,通常在这里:
TIdCookieManager.GenerateClientCookies()
有人知道如何解决这个问题吗?
【问题讨论】:
-
你到底在用 OnNewCookie 分配做什么?当我看到多层指针转换,包裹在一个匿名方法上,以
end )^ ) + $0C)^;之类的东西结尾时,我有点紧张。 -
我同意这不是最好的代码,但正如我在代码中所写的那样,OnNewCookie 可以使本地和全局 Cookie 管理器保持同步(据我所知,问题是不与 OnNewCookie 事件)
-
我同意@MasonWheeler。
OnNewCookie事件需要对象实例的非静态方法,而不是匿名过程。TIdCookieManager将向事件处理程序传递一个隐藏的Self指针,但您的匿名参数没有考虑到这一点,因此其余的事件参数将被搞砸。 -
谢谢大家,我转换为普通方法,但在 AddCookies() 中仍然出现异常,最后一个发生在此过程中
FRWLock.BeginWrite;TIdCookies.LockCookieList(AAccessType: TIdCookieAccess): TIdCookieList;的行中跨度> -
您在哪里实例化和释放
GlobalCookieManager对象?由于它在全球范围内使用,因此您应该在单元的initialization和finalization块中这样做。
标签: multithreading delphi delphi-2010 indy