需要有关Delphi多线程文件编写的帮助

BF2015

我正在编写一个Delphi dll,用于计算结果并将其写入CSV文件。调用程序是多线程的,因此一个问题是同时多次写入文件,这会导致调用程序崩溃。我试图使用关键部分来锁定文件写入,但是仍然会发生崩溃。如果我将程序配置为仅使用一个线程,问题将消失。下面是我的代码:

    library Question;

    uses
      SysUtils,
      Classes,
      Math,
      SyncObjs;

    {$R *.res}

    Var

        Outputfile: textfile;

        CriticalSection: TCriticalSection;

        CalNumb: integer = 0;

        PrintString: String;

    Threadvar

    Cal1, Cal2, Cal1Last: double;

    Function Calculator (input1, input2, input3, input4: double; 
    Factor: double; LastCal: Boolean; Print: integer): double stdcall;

    Const
        Divisor = 4;
    Var
        Temp: double;
    Begin

    Cal1Last:= Cal1;
    Cal1:= (input1+ input2+input3+ input4)/Divisor;
    Cal2:= (Cal1+Factor*Cal1Last)/2;
    Temp:= Cal2 - Cal1Last;

          If LastCal and (Print = 1) then
                begin

                  CriticalSection:= TCriticalSection.Create;
                  Try
                    Try
                      Inc(CalNumb);
                      Assign(Outputfile, 'C:\Calculator\Result.csv');
                      If FileExists('C:\Calculator\Result.csv') then 
                      Append(Outputfile) else rewrite (Outputfile);

                      If CalNumb = 1 then
                      begin
                        PrintString:= 'CalNumb' + ',' + 'Cal1' + ',' + 
                        'Cal1Last' + ',' + 'Cal2' + ',';

                        Writeln(Outputfile, PrintString);
                      end;


                      Writeln(Outputfile,
                      CalNumb, ',', Cal1:5:2, ',', Cal1Last:5:2, ',', Cal2:5:2, ',');


                    Finally
                      Close(Outputfile);
                    End;

                  Finally
                    CriticalSection.Free;
                  End;

                end;

    If Cal1 <> 0 then Calculator:= Temp/Cal1 else Calculator:= 0;

    End;

    Exports
           Calculator;

    begin
    end.

我的代码中有任何错误吗?多线程计算和外部文件编写对于该项目至关重要。您有什么建议和意见吗?我是一个初学者,所以如果您可以在此处发布代码,对我来说将是很大的帮助。提前非常感谢您!///////////////////////////////////////////////////// ////////////////////////////////////////////////////

Graymatter,谢谢您的建议。在完成您建议的更改后,应用程序将崩溃,然后再写入文件。dll的早期版本可以在崩溃前将某些数据行写入文件。万一我可能进行错误的更改,请在下面发布更改的部分。该代码的另一部分未更改。

          If LastCal and (Print = 1) then
                begin

                  CriticalSection.Acquire;
                  Try
                    Try
                      Inc(CalNumb);
                      Assign(Outputfile, 'C:\Calculator\Result.csv');
                      If FileExists('C:\Calculator\Result.csv') then 
                      Append(Outputfile) else rewrite (Outputfile);

                      If CalNumb = 1 then
                      begin
                        PrintString:= 'CalNumb' + ',' + 'Cal1' + ',' + 
                        'Cal1Last' + ',' + 'Cal2' + ',';

                        Writeln(Outputfile, PrintString);
                      end;


                      Writeln(Outputfile,
                      CalNumb, ',', Cal1:5:2, ',', Cal1Last:5:2, ',', Cal2:5:2, ',');


                    Finally
                      Close(Outputfile);
                    End;

                  Finally
                    CriticalSection.Release;
                  End;

                end;

    If Cal1 <> 0 then Calculator:= Temp/Cal1 else Calculator:= 0;

    End;

    Exports
           Calculator;

    begin
    end.


    initialization
      CriticalSection := TCriticalSection.Create;
    finalization
      CriticalSection.Free;
    end;
灰质

创建关键部分对象不会进行任何锁定。您需要致电Acquire以获取锁定并Release释放锁定。

请参阅在线帮助中的使用关键部分

问题是,在加载DLL时需要创建关键部分,因此您需要执行以下操作:

begin
  ...
  CriticalSection.Acquire;
  try
    ...
    // The code that needs to be locked goes inside here.
    // In your case it would be the code that opens the file
    // and appends the data.
    ...
  finally
    CriticalSection.Release;
  end;
  ...
end;

您将必须将代码移到一个单独的单元中,以便您可以包含initializationfinalization阻止。这些块将分别在首次加载DLL和卸载DLL时执行。

您的新单元将如下所示:

unit UnitForDLL;

interface

function Calculator(input1, input2, input3, input4: double; 
  Factor: double; LastCal: Boolean; Print: integer): double; stdcall;

implementation

uses
  SyncObjs, SysUtils;

var
  ...
  CriticalSection: TCriticalSection;
  ...

function Calculator(input1, input2, input3, input4: double; 
  Factor: double; LastCal: Boolean; Print: integer): double; stdcall;
begin
  ...
  CriticalSection.Acquire;
  try
    ...
    // The code that needs to be locked goes inside here.
    // In your case it would be the code that opens the file
    // and appends the data.
    ...
  finally
    CriticalSection.Release;
  end;
  ...
end;

initialization
  CriticalSection := TCriticalSection.Create;
finalization
  CriticalSection.Free;
end.

完成此操作后,您的项目本身将被更改为更加简单的内容:

library Question;

uses
  SysUtils,
  Classes,
  UnitForDLL;

{$R *.res}

exports
       Calculator;

begin
end.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

需要有关@autoreleasepool的帮助

来自分类Dev

需要有关fread()的帮助

来自分类Dev

需要有关风暴的帮助

来自分类Dev

需要有关getCartTotal()的帮助

来自分类Dev

需要有关NSString的帮助

来自分类Dev

需要有关iptables的帮助

来自分类Dev

需要有关SQL查询的帮助

来自分类Dev

需要有关AndEngine中精灵运动的帮助

来自分类Dev

需要有关“ menuTrigger”的javascript菜单的帮助

来自分类Dev

需要有关MYSQL QUERY(SUM)的帮助

来自分类Dev

需要有关未经检查的操作Java的帮助

来自分类Dev

需要有关PowerShell列循环的帮助

来自分类Dev

在JavaScript中需要有关“ this”的帮助

来自分类Dev

需要有关Java设计模式的帮助

来自分类Dev

需要有关SQL查询的帮助

来自分类Dev

我需要有关班级变量的帮助

来自分类Dev

需要有关PHP和HTML的帮助

来自分类Dev

需要有关函数别名的帮助

来自分类Dev

需要有关ffmpeg批处理脚本的帮助

来自分类Dev

需要有关GTK#和Mono的帮助

来自分类Dev

需要有关dhcpd.conf理解的帮助

来自分类Dev

需要有关CLLocationManager标题的帮助

来自分类Dev

随机冻结:需要有关mcelog的帮助

来自分类Dev

需要有关聚合函数的R编码的帮助

来自分类Dev

需要有关Web服务的帮助

来自分类Dev

需要有关SQL查询的帮助吗?

来自分类Dev

需要有关ALAsetsLibrary枚举的帮助

来自分类Dev

需要有关HTML和CSS代码的帮助〜

来自分类Dev

需要有关露天CMIS API的帮助