【发布时间】:2021-09-29 19:00:13
【问题描述】:
我有一个带有 TExecution 类的数字运算应用程序,该类包含在一个单独的单元 Execution.pas 中并执行所有计算。类实例是从程序的主要形式创建的。很多时候 Execution.pas 中的代码需要连续运行 10-15 次,我想在不同的线程中创建几个 TExecution 实例并并行运行它们。简化版代码如下:
其中有一个 Button1 的主窗体:
unit MainForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Threading, Execution;
type
TMainForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;
var
MainForm1: TMainForm1;
implementation
{$R *.dfm}
procedure TMainForm1.Button1Click(Sender: TObject);
var
ExecutionThread: array of TThread;
NoThreads: integer;
Execution: array of TExecution;
thread_ID: integer;
begin
NoThreads := 5;
SetLength(Execution,NoThreads);
SetLength(ExecutionThread,NoThreads);
//----------------------------------------------------------------------------------
for thread_ID := 0 to Pred(NoThreads) do
begin
ExecutionThread[thread_ID] := TThread.CreateAnonymousThread(
procedure
begin
try
Execution[thread_ID] := TExecution.Create;
Execution[thread_ID].CalculateSum;
finally
if Assigned(Execution[thread_ID]) then
begin
Execution[thread_ID] := nil;
Execution[thread_ID].Free;
end;
end;
end);
ExecutionThread[thread_ID].FreeOnTerminate := true;
ExecutionThread[thread_ID].Start;
end;
end;
end.
Execution.pas 单位:
unit Execution;
interface
uses
System.SysUtils, Vcl.Dialogs, System.Classes, WinApi.Windows;
type
TExecution = Class
const
NoOfTimes = 1000000;
var
Sum: integer;
private
procedure IncrementSum(var Sum: integer);
published
procedure CalculateSum;
End;
implementation
procedure TExecution.CalculateSum;
var
i: integer;
begin
Sum := 0;
for i := 0 to Pred(NoofTimes) do
begin
IncrementSum(Sum);
end;
end;
procedure TExecution.IncrementSum(var Sum: integer);
begin
Inc(Sum);
end;
end.
每当我通过单击 Button1 运行上述代码时,TExecution 实例都会运行,但是当我关闭程序时,我在函数 SysFreeMem 中的 GetMem.inc 中遇到访问冲突。显然,代码弄乱了内存,我猜是因为并行内存分配,但我无法找到原因并解决它。 我注意到,使用一个线程(NoThreads := 1),或串行执行代码(使用单个新线程和 5 个 TExecution 实例,或者直接从 MainForm 创建 TExecution 实例时),我没有得到类似的记忆问题。我的代码有什么问题? 非常感谢!
【问题讨论】:
-
为什么不马上
TExecution = Class( TThread )? -
只是因为我没有考虑过(而且我从没想过这是可能的)。如何创建线程,调用计算程序,然后销毁类?语法是一样的,但是在新线程中创建新类?
-
那是class inheritance:您将从
TExecute实例化对象,这是TThread的扩展,只需使用您的附加变量/过程。欢迎来到 OOP。
标签: multithreading delphi