我正在搞乱Delphi 2009提供的Indy 10,并且在OnExecute触发时无法从IOHandler获取所有数据......
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
  RxBufStr: UTF8String;
  RxBufSize: Integer;
begin
  if AContext.Connection.IOHandler.Readable then
  begin
    RxBufSize := AContext.Connection.IOHandler.InputBuffer.Size;
    if RxBufSize > 0 then
    begin
      SetLength(RxBufStr, RxBufSize);
      AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr), RxBufSize, False);
    end;
  end;
end;
AContext.Connection.IOHandler.InputBuffer.Size似乎不可靠并经常返回0,但是在下一次运行时,OnExecute它将获取正确的字节数,但为时已晚.
基本上我希望能够只获取所有数据,将其填充到UTF8String(不是 Unicode字符串),然后解析一个特殊的标记.所以我没有标题,消息长度可变.似乎Indy 10 IOHandlers没有为此设置,或者我只是错误地使用它.
做一些像传递一定大小的缓冲区,尽可能多地填充它并返回实际填充的字节数然后继续运行(如果还有更多)会很好.
除了TIdSchedulerOfFiber的状态之外,这看起来非常有趣,它有用吗?有人用吗?我注意到它不在Delphi 2009的标准安装中.
更新:我发现Msg:= AContext.Connection.IOHandler.ReadLn(#0,enUTF8); 哪个有效,但我仍然想知道上述问题的答案,是因为它是基于阻止IO吗?这使得TIdSchedulerOfFiber更加热衷于此.
这是一个很长的问题,但我们走了.有一个版本的FormatDateTime,据说是您使用的线程安全
GetLocaleFormatSettings(3081, FormatSettings); 
得到一个值然后你可以像这样使用它;
FormatDateTime('yyyy', 0, FormatSettings); 
现在想象两个计时器,一个使用TTimer(间隔说1000毫秒),然后另一个计时器创建如此(10毫秒间隔);
CreateTimerQueueTimer
(
  FQueueTimer, 
  0, 
  TimerCallback, 
  nil, 
  10, 
  10, 
  WT_EXECUTEINTIMERTHREAD
);
现在是一点点,如果在回调和计时器事件中你有以下代码;
for i := 1 to 10000 do
begin
  FormatDateTime('yyyy', 0, FormatSettings);
end;
请注意,没有任务.这会产生几乎立即访问的访问权限,有时甚至会在20分钟后随机出现.现在,如果您在C++ Builder中编写该代码,它永远不会崩溃.我们使用的标头转换是JEDI JwaXXXX.即使我们在代码中放入Delphi版本的锁,它也只会延迟不可避免的.我们已经查看了原始的C头文件,它看起来都很好,C++使用Delphi运行时有什么不同的方式吗?FormatDatTime的线程安全版本看起来是可重入的.任何可能以前看过这个的人的想法或想法.
更新:
为了缩小这一点,FormatSettings作为const传入,所以如果它们使用相同的副本(因为事实证明在函数调用中传递本地版本会产生同样的问题)是否重要?采用FormatSettings的FormatDateTime版本也不会调用GetThreadLocale,因为它已经具有FormatSettings结构中的Locale信息(我通过单步执行代码仔细检查).
我提到没有任何分配,以明确没有访问共享存储,因此不需要锁定.
WT_EXECUTEINTIMERTHREAD用于简化问题.我的印象是你应该只将它用于非常短的任务,因为它可能意味着如果它运行的时间很长,它会错过下一个间隔吗?
如果使用普通的旧TThread,则不会出现问题.我在这里得到的是我认为使用TThread或TTimer可以工作,但是使用在VCL外部创建的线程没有,这就是为什么我问C++ Builder使用VCL/Delphi RTL的方式是否存在差异.
顺便说一句,前面提到的代码也会失败(但需要更长时间),过了一会儿,CS:= TCriticalSection.Create;
  CS.Acquire;
  for i := 1 to LoopCount do
  begin
    FormatDateTime('yyyy', 0, FormatSettings);
  end;
  CS.Release;
现在我真的不明白,我按照建议写了这个;
function ReturnAString: string;
begin
  Result := 'Test';
  UniqueString(Result);
end;
然后在每种类型的计时器内部代码;
  for i := 1 to 10000 do
  begin
    ReturnAString;
  end;
这会导致相同类型的故障,正如我之前所说,故障永远不会出现在CPU窗口内的同一位置等.有时它是一种访问冲突,有时它可能是一个无效的指针操作.我正在使用Delphi 2009 …
我已经设法使用CertOpenSystemStore打开证书存储区,我可以使用我通过Windows Vista Ultimate上的MMC控制台安装的CertFindCertificateInStore找到我的自签名证书(使用OpenSSL创建).但是我不确定这个错误到底是什么意思,因为我无法在MSDN文档中找到答案.这是证书问题吗?或者操作系统问题,从某种意义上说它应该是一个Windows Server操作系统来实现这一点?
我在Delphi 2010中使用Win32 API,但C示例很好.
谢谢,布鲁斯
我想使用Delphi 2009的FFTW C库并根据本文档;
http://www.fftw.org/install/fftw_usage_from_delphi.txt
为了提高FFTW库内的性能(使其可以使用SIMD扩展),传入Single(float)或Double(double)的数组需要在4或8字节边界对齐.我找到了关于记录结构对齐的文档,但没有关于数组的具体内容.在Delphi 2009中有没有办法做到这一点.
所以代码(从上面的文档中复制)看起来像这样;
var
      in, out : Array of Single; // Array aligned at 4 byte boundary
      plan : Pointer;
    {$APPTYPE CONSOLE}
    begin
      ...  
      SetLength(in, N);
      SetLength(out, N);
      plan := _fftwf_plan_dft_1d(dataLength, @in[0], @out[0],
                                 FFTW_FORWARD, FFTW_ESTIMATE);
同样在上面的文档中,他们讨论了8和16字节的边界,但它看起来它应该是4和8字节边界,如果有任何可以清除,那将是伟大的.
谢谢,布鲁斯
我在TIdTCPServer的OnExecute中有以下代码(随安装附带的Delphi 2009和Indy 10),这与本网站上的其他示例非常相似;
   Socket := AContext.Connection.Socket;
    if Socket.CheckForDataOnSource(10) then
    begin
      if not Socket.InputBufferIsEmpty then
      begin
        Socket.InputBuffer.ExtractToBytes(RawBytes, -1, False, -1);
        SetLength(Buffer, Length(RawBytes));
        Move(RawBytes[0], Buffer[1], Length(RawBytes));
        // Do stuff with data here...
      end;
    end;
    AContext.Connection.CheckForGracefulDisconnect;
它有时不会读取数据,因为CheckForDataOnSource(10)返回False.但是,如果我在该行停止调试器,我可以看到我在InputBuffer的字节中发送的数据.是否还有其他任何我应该做的设置或其他方法来强制它一直工作.这段代码运行很多次但总是在CheckForDataOnSource(10)上失败.
另外作为旁注,我注意到Indy的代码周围有些人抓住了AContext.Connection.IOHandler而不是AContext.Connection.Socket并做了与上面的代码相同的事情,什么是"正确"的使用.
谢谢
布鲁斯