流读取错误

时间:2011-03-15 21:34:19

标签: delphi delphi-2010

我在重负载下收到此错误消息。这是我的错误日志中的代码摘要和消息。 我尝试了我能想到的一切。任何建议都将不胜感激。

Procedure tCacheInMemory.StreamValue(Name: String; IgnoreCase: Boolean; Var Stream:     TStringStream);
Var
  i: Integer;
Begin
  i := 0;
  Try
    If Not active Then
      exit;
    arrayLock.BeginRead;
    Try
      i := Search(Name);
      If i > -1 Then Begin
        If fItems[i].value = Nil Then
          exit;
        fItems[i].value.Position := 0;
        Stream.Position := 0;
        Stream.CopyFrom(fItems[i].value, fItems[i].value.Size);
      End;
    Finally
      arrayLock.EndRead;
    End;
  Except { ...execution jumps to here }
    On E: Exception Do Begin
      x.xLogError('LogErrorCacheInMemory.txt', 'StreamValue:' + E.Message + ' ItemsCount:' + IntToStr( High(fItems)) + 'Memory:' + IntToStr(x.GetMemoryInfoMemory) + endLn + 'StreamSize : ' + IntToStr(fItems[i].value.Size) + ' i=' + IntToStr(i) + 'Name: ' + Name);
      Clear;
    End
  End;
End;

日志条目:

 3/10/2011 10:52:59 AM: StreamValue:Stream read error ItemsCount:7562 Memory:240816
   StreamSize : 43 i=7506 Name: \\xxxxxxxx\WebRoot\\images\1x1.gif
3/10/2011 12:39:14 PM: StreamValue:Stream read error ItemsCount:10172 Memory:345808
   StreamSize : 849 i=10108 Name: \\xxxxxxxx\WebRoot\\css\screen.add.css
3/10/2011 3:45:29 PM: StreamValue:Stream read error ItemsCount:11200 Memory:425464
   StreamSize : 3743 i=11198 Name: \\xxxxxxxx\WebRoot\\JS\ArtWeb.js

P.S。

arrayLock: TMultiReadExclusiveWriteSynchronizer;
 fItems: Array Of rCache;
Type
  rCache = Record
    Name: String;
    value: TStringStream;
    expired: TDateTime;
  End;

并且调用函数:

Function tCacheInMemory.CacheCheck(cName: String; Out BlobStream: TStringStream):   Boolean;
Begin
Result := False;
   If Not IfUseCache Then
      exit;
    BlobStream.SetSize(0);
    BlobStream.Size := 0;
    StreamValue(trim(cName), True, BlobStream);
    If BlobStream.Size > 0 Then
    Result := True;
End;

`

2 个答案:

答案 0 :(得分:8)

您没有使用正确的锁定。您正在获取缓存条目数组上的读取锁定,但是一旦找到所需的项目,就可以修改它。首先,您通过分配其Position属性显式修改它,然后通过读取隐式修改它,修改其Position属性再次。当其他代码尝试从同一个缓存项读取时,您将受到干扰。如果源流的Position属性在目标流计算可用字节数和实际请求读取这些字节的时间之间发生变化,则会出现流读取错误。

我有几条与此相关的建议:

  • 首先不要将流用作存储设备。你显然是持有文件的内容。您不会更改它们,因此您不需要为进行顺序更改而设计的数据结构。相反,只需将数据存储在简单的字节数组中:TBytes。 (另外,TStringStream的使用特别引起了对这些字符串编码是否重要的​​混淆。简单的文件缓存根本不应该与字符串编码有关。如果必须使用stream,使用与TMemoryStream类似的内容无关的类。)
  • 不要平息您实际未处理的异常。在此代码中,您将捕获所有异常类型,记录一些信息,清除缓存,然后继续进行,就好像一切正​​常一样。但是你没有做任何事情来解决触发异常的问题,所以一切都正常。由于您并未真正处理异常,因此需要确保它传播给调用方。致电raise后致电Clear。 (当您记录异常时,请确保记录异常的ClassName值及其消息。)

答案 1 :(得分:1)

<击> 外观似乎阻止了你的流文件。

您可以尝试使用Process Monitor查看阻止它的内容。

您可以尝试的另一件事是以read-deny-write模式打开流(请告诉我们您如何打开流)。

这样的事情:

Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite) ;

<击>

编辑1:忽略部分攻击:您正在使用TStringStream。
我会保留答案,以防万一有人在使用TFileStream时遇到这种错误。

编辑2: Yuriy发布了这个有趣的附录,但我不确定它是否有效,因为BlobStream未初始化,就像{{3}一样怀疑:

Function TCacheInMemory.CacheCheck(cName: String; Out BlobStream: TStringStream): Boolean; 
Begin 
  Result := False; 
  Try 
    If Not IfUseCache Then 
      exit; 
    BlobStream.SetSize(0);  
    BlobStream.Size := 0;  
    StreamValue(trim(cName), True, BlobStream);  
    If BlobStream.Size > 0 Then  
      Result := True;  
  Except  
    On E: Exception Do  
    Begin  
      x.xLogError('LogErrorCacheInMemory.txt', 'CheckCacheOutStream:' + E.Message + ' ItemsCount:' + IntToStr( High(fItems)) + 'Memory:' + IntToStr(x.GetMemoryInfoMemory));  
    End;  
  End;  
End; 

- 的Jeroen