I/O error 32/103

来源:互联网 发布:数据挖掘和数学建模 编辑:程序博客网 时间:2024/04/29 17:25

        最近做的一个项目需要不断的对Text文件进行写访问,最终操作文件的函数只有一个,且在主线程,线程中对此文件的操作采用同步到主线程的方式进行。看似天衣无缝的完美,在运行过程中还是出现操作文件异常的错误。

        环境概述:win7系统。问题出现的情况是TidhttpServer的OncommandGet事件触发时。虽然是多线程,但是程序的机制是确保只有一个子线程运行结束后再进行下一个子线程,所以当OncommandGet事件没有触发时,程序确保写文件函数是正常运行的。当所有线程不启动,只有OncommandGet事件触发时,程序一切正常。

        最开始我猜测的是因为OncommandGet事件可能具有cpu抢占优先权,所以当一个线程正在同步调用写文件函数时,文件还未关闭,OncommandGet事件触发占得Cpu使用权,并调用了文件操作函数导致错误产生。

最初的写文件测试函数:

procedure TForm1.WriteFile(ptxt: string);
var
  tfname: string;
begin
  tfname:=extractfilepath(paramstr(0))+'BossLog\';
  if not directoryexists(tfname) then
    createdir(tfname);

    tfname:=tfname+formatdatetime('YYYYMMDD',now)+'.log';
    AssignFile(logFile,tfname);

      if not FileExists(tfname) then
    begin
      Rewrite(logFile);
      writeln(logFile,formatdatetime('YYYY-MM-DD HH:MM:SS',now)+'> 日志开始'+#13+#10);
      CloseFile(logFile);
    end;
    try
      append(logFile);/  /一般在这里容易报错
      writeln(logfile,ptxt);
      CloseFile(logFile);

    except
      CloseFile(logFile);  //报错后这样也是无用的
    end;

end;

       通过测试程序的各种情况的测试,现在我更认为是可能对文件访问时顺序的没有重叠抢占的情况,但是调用CloseFile结束时候文件并没有真的关闭结束处于就绪状态,此时立马进行文件操作就会报错。这一点从以下代码中得出:

增加了临界区之后的代码:

procedure TForm1.WriteFile(ptxt: string);
var
  tfname: string;
begin
  tfname:=extractfilepath(paramstr(0))+'BossLog\';
  if not directoryexists(tfname) then
    createdir(tfname);
 try

    tfname:=tfname+formatdatetime('YYYYMMDD',now)+'.log';
    AssignFile(logFile,tfname);

      if not FileExists(tfname) then
    begin
      Rewrite(logFile);
      writeln(logFile,formatdatetime('YYYY-MM-DD HH:MM:SS',now)+'> 日志开始'+#13+#10);
      CloseFile(logFile);
    end;

    EnterCriticalSection(cs);    //将临界区的锁加在此处,当OncommandGet事件频发时,还是会出问题 ,于是在此行后增加了一行sleep(10),测试程序就没出现问题了,于是就得出了上述结论

    try
      append(logFile);
      writeln(logfile,ptxt);
      CloseFile(logFile);

    except

    end;
  finally
    LeaveCriticalSection(cs);
 end;
end;


  

最终测试代码:

procedure TForm1.WriteFile(ptxt: string);
var
  tfname: string;
begin
  tfname:=extractfilepath(paramstr(0))+'BossLog\';
  if not directoryexists(tfname) then
    createdir(tfname);
 try
     EnterCriticalSection(cs);  //将临界区提前锁,加强了对文件操作的控制,一定程度上保证文本目前处于闲置状态,程序目前为止还正常

    tfname:=tfname+formatdatetime('YYYYMMDD',now)+'.log';
    AssignFile(logFile,tfname);

      if not FileExists(tfname) then
    begin
      Rewrite(logFile);
      writeln(logFile,formatdatetime('YYYY-MM-DD HH:MM:SS',now)+'> 日志开始'+#13+#10);
      CloseFile(logFile);
    end;

    try
      append(logFile);
      writeln(logfile,ptxt);
      CloseFile(logFile);

    except

    end;
  finally
    LeaveCriticalSection(cs);
 end;
end;EnterCriticalSection(cs);  


具体的原因估计和操作系统的文件访问机制有关,我研究不深,若有心人看到有不对的地方望提醒补充。



0 0
原创粉丝点击