【发布时间】:2015-11-12 06:23:08
【问题描述】:
我正在编写一个 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.
我的代码有错误吗?多线程计算和外部文件写入对于这个项目是必不可少的。你有什么建议和cmets?我是初学者,所以如果你可以在这里发布你的代码,这对我来说将是一个很大的帮助。非常感谢您! ///////////////////////////////////////// //////////////////////////////////////////////// p>
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;
【问题讨论】:
-
您是否记录/调试过您的代码,您的代码的哪一行导致应用程序崩溃?:
-
当我注释文件分配,追加和写入块时,应用程序崩溃消失了。
-
在每个线程中写入单独的文件并在所有线程完成后将它们连接到最终文件中可能会更有效。
-
TOndrej,你的建议很棒。但是,我只能修改dll,不能修改应用程序。如何修改分配部分,以便每个线程可以写入不同的文件?似乎我无法将变量放入文件名或路径中。我知道它可以通过一些复杂的方式来完成。你能详细说明一下吗?谢谢!
-
作为一个初学者,你咬的比你能嚼的多。从您说您是多线程的事实中可以看出这一点,但根本没有显示与线程相关的任何内容。您正在创建的这些线程在哪里?
标签: multithreading file delphi io writing