- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 AsyncCalls 对整个 C 类子网执行 Netbios 查找。理想情况下,我希望它同时执行 10 次以上的查找,但目前它一次只执行 1 次查找。我在这里做错了什么?
我的表单包含 1 个按钮和 1 个备忘录。
unit main;
interface
uses
Windows,
Messages,
SysUtils,
Classes,
Forms,
StdCtrls,
AsyncCalls,
IdGlobal,
IdUDPClient,
Controls;
type
PWMUCommand = ^TWMUCommand;
TWMUCommand = record
host: string;
ip: string;
bOnline: boolean;
end;
type
PNetbiosTask = ^TNetbiosTask;
TNetbiosTask = record
hMainForm: THandle;
sAddress: string;
sHostname: string;
bOnline: boolean;
iTimeout: Integer;
end;
const
WM_THRD_SITE_MSG = WM_USER + 5;
WM_POSTED_MSG = WM_USER + 8;
type
TForm2 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
procedure ThreadMessage(var Msg: TMessage); message WM_POSTED_MSG;
{ Private declarations }
public
{ Public declarations }
end;
var
Form2 : TForm2;
implementation
{$R *.dfm}
function NetBiosLookup(Data: TNetbiosTask): boolean;
const
NB_REQUEST = #$A2#$48#$00#$00#$00#$01#$00#$00 +
#$00#$00#$00#$00#$20#$43#$4B#$41 +
#$41#$41#$41#$41#$41#$41#$41#$41 +
#$41#$41#$41#$41#$41#$41#$41#$41 +
#$41#$41#$41#$41#$41#$41#$41#$41 +
#$41#$41#$41#$41#$41#$00#$00#$21 +
#$00#$01;
NB_PORT = 137;
NB_BUFSIZE = 8192;
var
Buffer : TIdBytes;
I : Integer;
RepName : string;
UDPClient : TIdUDPClient;
msg_prm : PWMUCommand;
begin
RepName := '';
Result := False;
UDPClient := nil;
UDPClient := TIdUDPClient.Create(nil);
try
try
with UDPClient do
begin
Host := Trim(Data.sAddress);
Port := NB_PORT;
Send(NB_REQUEST);
end;
SetLength(Buffer, NB_BUFSIZE);
if (0 < UDPClient.ReceiveBuffer(Buffer, Data.iTimeout)) then
begin
for I := 1 to 15 do
RepName := RepName + Chr(Buffer[56 + I]);
RepName := Trim(RepName);
Data.sHostname := RepName;
Result := True;
end;
except
Result := False;
end;
finally
if Assigned(UDPClient) then
FreeAndNil(UDPClient);
end;
New(msg_prm);
msg_prm.host := RepName;
msg_prm.ip := Data.sAddress;
msg_prm.bOnline := Length(RepName) > 0;
PostMessage(Data.hMainForm, WM_POSTED_MSG, WM_THRD_SITE_MSG, integer(msg_prm));
end;
procedure TForm2.Button1Click(Sender: TObject);
var
i : integer;
ArrNetbiosTasks : array of TNetbiosTask;
sIp : string;
begin
//
SetMaxAsyncCallThreads(50);
SetLength(ArrNetbiosTasks, 255);
sIp := '192.168.1.';
for i := 1 to 255 do
begin
ArrNetbiosTasks[i - 1].hMainForm := Self.Handle;
ArrNetbiosTasks[i - 1].sAddress := Concat(sIp, IntToStr(i));
ArrNetbiosTasks[i - 1].iTimeout := 5000;
AsyncCallEx(@NetBiosLookup, ArrNetbiosTasks[i - 1]);
Application.ProcessMessages;
end;
end;
procedure TForm2.ThreadMessage(var Msg: TMessage);
var
msg_prm : PWMUCommand;
begin
//
case Msg.WParam of
WM_THRD_SITE_MSG:
begin
msg_prm := PWMUCommand(Msg.LParam);
try
Memo1.Lines.Add(msg_prm.ip + ' = ' + msg_prm.host + ' --- Online? ' + BoolToStr(msg_prm.bOnline));
finally
Dispose(msg_prm);
end;
end;
end;
end;
end.
最佳答案
棘手的事情。我做了一些调试(嗯,相当多的调试),发现 AsyncCallsEx 中的代码块位于第 1296 行:
Result := TAsyncCallArgRecord.Create(Proc, @Arg).ExecuteAsync;
进一步挖掘表明它在 System.pas (_IntfCopy) 中的接口(interface)复制中阻塞
CALL DWORD PTR [EAX] + VMTOFFSET IInterface._Release
查看相同代码的 pascal 版本,该行似乎释放了先前存储在目标参数中的引用计数。但是,目标是调用者(您的代码)中未使用的结果。
现在是棘手的部分。
AsyncCallEx 返回一个接口(interface)(在您的情况下)调用者会丢弃该接口(interface)。所以理论上编译后的代码(伪形式)应该是这样的
loop
tmp := AsyncCallEx(...)
tmp._Release
until
但是编译器将其优化为
loop
tmp := AsyncCallEx(...)
until
tmp._Release
为什么?因为它知道对接口(interface)进行赋值会自动释放tmp变量中存储的接口(interface)的引用计数(_IntfCopy中对_Release的调用)。因此无需显式调用 _Release。
但是,释放 IAsyncCall 会导致代码等待线程完成。所以基本上每次调用 AsyncCallEx 时都会等待前一个线程完成...
我不知道如何使用 AsyncCalls 很好地解决这个问题。我尝试了这种方法,但不知怎的,它并没有完全按预期工作(在 ping 大约 50 个地址后程序 block )。
type
TNetbiosTask = record
//... as before ...
thread: IAsyncCall;
end;
for i := 1 to 255 do
begin
ArrNetbiosTasks[i - 1].hMainForm := Self.Handle;
ArrNetbiosTasks[i - 1].sAddress := Concat(sIp, IntToStr(i));
ArrNetbiosTasks[i - 1].iTimeout := 5000;
ArrNetbiosTasks[i - 1].thread := AsyncCallEx(@NetBiosLookup, ArrNetbiosTasks[i - 1]);
Application.ProcessMessages;
end;
for i := 1 to 255 do // wait on all threads
ArrNetbiosTasks[i - 1].thread := nil;
关于multithreading - 是否可以使用 AsyncCalls 单元创建线程池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5671589/
我有2个功能: function func1() while true do -- listen on connection end end function func2()
我的问题可能看起来很奇怪,但我想我正面临着 volatile 的问题。对象。 我写了一个这样实现的库(只是一个方案,不是真正的内容): (def var1 (volatile! nil)) (def
由于 maven 支持多线程构建,是否可以同时运行 Sonar 多线程? (例如 mvn sonar:sonar -T 4 ) 我运行了它,当模块报告成功时,它报告整个构建失败并返回 java.uti
我们正在启动一个网站,该网站在短时间内的交易量非常大。它基本上是在给票。该代码是用Java,Spring和Hibernate编写的。我想通过产生多个线程并尝试使用JUnit测试用例来获取票证来模仿高容
我正在尝试访问像素数据并将图像从游戏中的相机保存到磁盘。最初,简单的方法是使用渲染目标,然后使用RenderTarget-> ReadPixels(),但是由于ReadPixels()的 native
我们有以下系统: 用户数:〜500k 项目数:〜100k UserSimilarity userSimilarity = new TanimotoCoefficientSimilarity(dataM
也许这是一个经常出现的问题,但我需要根据我的上下文进行一些自定义。 我正在使用 Spring Batch 3.0.1.RELEASE 我有一个简单的工作,有一些步骤。一个步骤是这样的 block :
也许这是一个经常出现的问题,但我需要根据我的上下文进行一些自定义。 我正在使用 Spring Batch 3.0.1.RELEASE 我有一个简单的工作,有一些步骤。一个步骤是这样的 block :
我正在尝试使用PyBrain和Python的multiprocessing软件包在Python中训练神经网络。 这是我的代码(它训练了一个简单的神经网络来学习XOR逻辑)。 import pybrai
我有一个繁重的功能,不适合在主时间轴上执行(因为要花很长时间才能完成并使程序崩溃)。 因此我在air(as3)中搜索多线程,但是我发现的所有示例都说明了如何在worker中运行单独的swf文件。如何在
我想实现线程A 和线程B 并行运行并共享全局变量。 下面是用python编写的代码。我想在中执行相同操作Dart (我不想使用future等待,因为它正在等待其他线程完成或必须等待。) 大小写变量:
我的一个项目只适用于调试 DLL,而不适用于非调试 DLL。 在 Debug DLL 设置下发布项目有哪些注意事项?例如,是否丢失了某些优化? 如何通过将调试版本设置为非调试 DLL 来调试此项目?我
我正在尝试比较 Matlab 和 Julia 之间的速度和性能。我正在查看一个代码,该代码对承受给定负载的连续体结构进行拓扑优化。我正在查看的代码是公共(public)代码topopt88.m:htt
Serving Flask 应用程序“服务器”(延迟加载) 环境:生产警告:这是一个开发服务器。不要在生产部署中使用它。请改用生产 WSGI 服务器。 Debug模式:开启 在 http://0.0.
我对 PyQT 很陌生。我正在学习如何制作 Progressbar 并随着算法的进展对其进行更新。我已经能够制作一个使用此链接进行 self 更新的基本进度条:Python pyqt pulsing
我正在尝试指定在特定线程上运行任务,这样我就可以使用两个专用于“放入” channel 的耗时任务的线程,而其他线程则用于处理该任务。 我对如何将特定任务分配给特定线程感到困惑。我以为我可以使用类似
我正在编写一个软件,它对很多(潜在的大)图像进行大量图像操作/合成。 多线程有助于提高速度,但 QT 不允许同时在同一图像上使用多个 QPainter。 所以我必须在副本的每个线程中进行图像操作/合成
此脚本读取 url 文件以执行多线程 HTTP 请求。 如何使用带有 url 的数组来发出多线程请求? 我的阵列将有类似的东西: @array = ("https://example.com/xsd"
Java 文档声明了以下关于构造函数同步的内容: Note that constructors cannot be synchronized — using the synchronized keyw
我有一个程序,其中主线程创建了很多线程。它崩溃了,我正在调试核心文件。崩溃发生在其中一个子线程中。为了找到原因,我需要知道主线程是否还活着。有什么方法可以找出哪个线程是初始线程? 最佳答案 Is th
我是一名优秀的程序员,十分优秀!