multithreading - Delphi的另一个单元中的多线程
问题描述
我在一个名为 Execution 的单元中有一个数字运算应用程序,它是从主窗体调用的。通常 Execution.pas 中的代码需要连续运行 10-15 次,我正在寻找一种应用多线程的有效方法,以便执行单元上的计算并行运行。代码的简化版本如下:
带有一个 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, 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: TThread;
run_ID: integer;
begin
for run_ID := 0 to 2 do
begin
ExecutionThread := TThread.CreateAnonymousThread(
procedure
begin
Execution.CalculateSum;
end);
ExecutionThread.FreeOnTerminate := true;
ExecutionThread.Start;
end;
end;
end.
Execution.pas 单位:
unit Execution;
interface
uses System.SysUtils, Vcl.Dialogs;
procedure CalculateSum;
procedure IncrementSum(var Sum: integer);
implementation
const
NoOfTimes = 100;
var
Sum: integer;
procedure CalculateSum;
var
i: integer;
begin
Sum := 0;
for i := 0 to Pred(NoofTimes) do
begin
IncrementSum(Sum);
end;
ShowMessage('Sum = ' + IntToStr(Sum));
end;
procedure IncrementSum(var Sum: integer);
begin
Inc(Sum);
Sleep(10);
end;
end.
如果我执行简化的代码,我会收到三条消息,总和接近 300,但不是 300(285、287、289),这是预期的,因为所有线程同时更改相同的全局变量 Sum,有时还会更改增量重叠。
有没有一种简单的方法可以为每个线程分配不同的内存,以便我得到三条总和为 100 的消息?还是我必须自己硬编码,在每个线程中分配不同的执行变量?
请注意,我拥有的原始应用程序包含数千个变量和记录,因此我正在寻找一种快速的方法来执行此操作而不会显着更改代码(当然,如果有的话)。
先感谢您。
解决方案
你有没有想过使用TCriticalSection
in System.SyncObjs
?
一次只能有一个线程进入TCriticalSection,所以如果一个线程进入,修改共享变量,然后离开,那么每个线程都会等待其他线程。
如果您将大部分时间花在 TCriticalSection 中,这将无法帮助您进行扩展,因为您的线程将主要等待对象,但它确实确保一次只有一个线程正在修改受 TCriticalSection 保护的数据。
因此,如果您的代码不断更新共享变量,这将阻止它们发生冲突,但不会真正提供单独线程的好处。但是,如果线程在不修改变量的情况下进行大量计算,那么这允许该代码并行执行。
推荐阅读
- django - Python 3.7 AttributeError:“str”对象没有属性“has”
- php - 传递给 Laravel 函数的参数太少
- oracle - 如何为成千上万的人使用不同的组分隔符。甲骨文
- html - 为什么阿拉伯语 Noto 字体(或其他阿拉伯语字体)在 HTML / CSS 中呈现不正确?
- c# - 尝试通过 C# API 订阅时,主题到队列映射失败
- reactjs - 无法从可编辑圆 onRadiusChanged 事件中获取半径值
- c++ - 如何将变量定义传递给函数?
- css - Firefox 是否仍需要“::moz-selection”来更改 wordpress 中的背景文本颜色?
- python - 网页抓取:无法使用类循环进入 div 元素以获取文本和 URL
- java - Java中文件压缩到固定大小