我有一个类(TObject):
private
FHwnd : HWND;
procedure HandleMyMessage(var Message : TMessage); message TH_MYMESSAGE;
Run Code Online (Sandbox Code Playgroud)
哪里 TH_MYMESSAGE = WM_USER + 1
在类构造函数中:
FHwnd := AllocateHWND(HandleMyMessage);
Run Code Online (Sandbox Code Playgroud)
接收引用的唯一对象FHwnd是私有自定义TThread(在此类中创建)以及它发布的唯一消息TH_MYMESSAGE.我的理解是,message程序声明中的指令仅限制其处理TH_MYMESSAGE.
这在测试中运行良好,但是在集成到更大的应用程序中时,我得到的反馈HandleMyMessage也会触发其他消息(显然有不希望的结果).
这可以通过添加if Message.Msg <> TH_MYMESSAGE then Exit;来轻松纠正HandleMyMessage.我的问题是:为什么会这样?
我最好的猜测是,AllocateHWND已经取得HandleMyMessage的等效DefWndProc尽管拥有它message的指令.有没有正确的方法来实现我缺少的?
我正在尝试Delphi XE7 Update 1的并行编程功能.
我创建了一个简单的TParallel.For循环,基本上做了一些虚假的操作来消磨时间.
我在AWS实例(c4.8xlarge)上的36 vCPU上启动了该程序,试图了解并行编程的优势.
当我第一次启动程序并执行TParallel.For循环时,我看到了显着的增益(虽然admitelly比我预期的36个vCPU少很多):
Parallel matches: 23077072 in 242ms
Single Threaded matches: 23077072 in 2314ms
Run Code Online (Sandbox Code Playgroud)
如果我不关闭程序并在不久之后再次在36 vCPU机器上运行传递(例如,立即或大约10-20秒后),并行传递会恶化很多:
Parallel matches: 23077169 in 2322ms
Single Threaded matches: 23077169 in 2316ms
Run Code Online (Sandbox Code Playgroud)
如果我没有关闭程序并等待几分钟(不是几秒钟,但几分钟)再次运行传递之前,我再次得到第一次启动程序时得到的结果(响应时间提高了10倍) .
在36个vCPU机器上启动程序后的第一次传递总是更快,因此看起来这种效果仅TParallel.For在程序中第二次调用a时发生.
这是我正在运行的示例代码:
unit ParallelTests;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
System.Threading, System.SyncObjs, System.Diagnostics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
SingleThreadCheckBox: TCheckBox;
ParallelCheckBox: TCheckBox;
UnitsEdit: TEdit;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ …Run Code Online (Sandbox Code Playgroud) 几个月前,一位同事提到我,我们的一个内部Delphi应用程序似乎占用了8 GB的RAM.我告诉他了:
那是不可能的
32位应用程序仅具有32位虚拟地址空间.即使存在内存泄漏,它可以消耗的内存最多也是2 GB.之后,分配将失败(因为虚拟地址空间中不会有空白空间).在内存泄漏的情况下,虚拟页面将被换出到页面文件,从而释放物理RAM.
但他指出Windows资源监视器表明系统上可用的RAM不到1 GB.虽然我们的应用程序仅使用220 MB的虚拟内存:关闭它可以释放8 GB的物理RAM.
我让应用程序运行了几个星期,今天我终于决定测试它.
首先,我在关闭应用程序之前查看内存使用情况:
我使用资源监视器来检查应用程序使用的内存,以及正在使用的总RAM:
然后关闭应用程序后的内存使用情况:
我还使用Process Explorer来查看前后物理RAM使用情况的细分.唯一的区别是8 GB的RAM 确实是未提交的,现在是免费的:
| Item | Before | After |
|-------------------------------|------------|-----------|
| Commit Charge (K) | 15,516,388 | 7,264,420 |
| Physical Memory Available (K) | 1,959,480 | 9,990,012 |
| Zeroed Paging List (K) | 539,212 | 8,556,340 |
Run Code Online (Sandbox Code Playgroud)
注意:Windows有时会浪费时间将所有内存清零,而不是简单地将其放在备用列表中,并根据需要将其清零(因为需要满足内存请求).
这些都没有解释RAM正在做什么(你坐在那里做什么!你包含什么!?)
如果保证每个线程只读/写一个特定的数组子集,多个线程可以在同一个(静态)数组上工作,而不需要求助于关键部分等?
编辑 - 这是针对非参考计数类型的数组及其记录/打包记录的特定情况.
如果是,有任何警告吗?
我的直觉是肯定的,但我的直觉有时可能是一个不可靠的信息来源.
考虑以下 :
{$APPTYPE CONSOLE}
uses
Generics.Collections;
type
TObjProc = procedure of object;
TFoo = class
public procedure DoFoo;
public procedure DoBar;
end;
procedure TFoo.DoFoo;
begin
WriteLn('foo');
end;
procedure TFoo.DoBar;
begin
WriteLn('bar');
end;
var
ProcList : TList<TObjProc>;
Foo : TFoo;
aProc : TObjProc;
begin
Foo := TFoo.Create;
ProcList := TList<TObjProc>.Create;
ProcList.Add(Foo.DoFoo);
ProcList.Add(Foo.DoBar);
for aProc in ProcList do aProc;
ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)
这产生了预期的输出
foo
bar
Run Code Online (Sandbox Code Playgroud)
现在假设我们要从列表中分配一个过程.列举作品,如上所述.这也有效:
aProc := ProcList.Items[0];
aProc;
Run Code Online (Sandbox Code Playgroud)
但这会引发编译器错误:
aProc := ProcList.First;
// E2010 Incompatible types:
//'procedure, untyped pointer or …Run Code Online (Sandbox Code Playgroud) 我正在使用Delphi 2010,我想知道是否有一种方法可以跟踪项目中的代码,而无需跟踪调用包含的VCL.
例如 - 您输入一个断点然后使用Shift+ F7来逐行跟踪.现在你在VCL中调用了一些冗长的过程 - 在我的例子中,它通常是一个Measurement Studio或其他组件,用于绘制一堆I/O,OPC或其他位的doodads.无论如何,发生的事情是调试器跳出活动源文件,打开组件源,并逐行跟踪.通常这是我不关心的数百或数千行代码 - 我只想让它执行并返回到MY项目中的下一个源代码行.
显然你可以通过在外部调用的每个实例周围设置断点来实现这一点,但通常有太多不能使其变得切实可行 - 每次我想要逐步执行一段代码时,我会花一小时设置一百个断点.
是否有设置或工具可以做到这一点?允许用户跟踪项目中的代码,同时静默执行项目外部的代码?
我编写了一个具有覆盖类型窗口的应用程序,可以通过热键显示和隐藏,而另一个应用程序具有焦点.所述其他应用程序是使用管理员权限运行的DirectX游戏.
我已经尝试了3种可能的解决方案,当我在其他应用程序中按下热键时收到通知,其中2种工作,但要求我的应用程序也具有管理权限.这是可以接受的,但我宁愿有一个不需要这些特权的解决方案.我确信必须有一种方法,因为像TeamSpeak这样的应用程序确实能够在不以管理员身份运行的情况下接收输入.
我已经尝试过了:
所以,是的,如果有人可以为不同的解决方案提供一个想法,我会非常感激,因为我无法想到......我正在使用Delphi,但是因为我依赖Windows API,所以我不这样做认为解决方案将特定于语言.
Delphi 文档说明:
永远不要直接引发EInvalidPointer异常.EInvalidPointer由内存管理器在内部引发.
我正在编写一个自定义基类作为替代TInterfacedObject,尽可能地遵循RTL实现,并且通过示例看,TInterfacedObject在RTL实现BeforeDestruction为:
procedure TInterfacedObject.BeforeDestruction;
begin
if RefCount <> 0 then
Error(reInvalidPtr);
end;
Run Code Online (Sandbox Code Playgroud)
其中Error(reInvalidPtr)提出了EInvalidPointer通过各种本地的RTL单元范围的方法.
如果我正在编写自己的课程,我应该如何实施BeforeDestruction?为什么不这样做?:
procedure TMyInterfacedObject.BeforeDestruction;
begin
if RefCount <> 0 then
raise EInvalidPointer.CreateRes(@SInvalidPointer) at ReturnAddress;
end;
Run Code Online (Sandbox Code Playgroud)
InvalidPointer声明的全局异常对象是否有特殊之处SysUtils?如果这是一个坏主意,那么在这里简单地提出一个自定义异常是否明智?
对于32位Windows应用程序,使用ESP下面的堆栈内存进行临时交换空间而不显式减少ESP是有效的吗?
考虑一个返回浮点值的函数ST(0).如果我们的价值目前在EAX,我们会,例如,
PUSH EAX
FLD [ESP]
ADD ESP,4 // or POP EAX, etc
// return...
Run Code Online (Sandbox Code Playgroud)
或者不修改ESP寄存器,我们可以:
MOV [ESP-4], EAX
FLD [ESP-4]
// return...
Run Code Online (Sandbox Code Playgroud)
在这两种情况下都会发生同样的事情,除了在第一种情况下我们注意在使用内存之前递减堆栈指针,然后在之后递增它.在后一种情况下,我们没有.
尽管有任何实际需要在堆栈上持久保存这个值(重入问题,在PUSH返回值和读取值之间的函数调用等),有没有任何根本原因,为什么写入ESP下面的堆栈这样会无效?