我创建了一个小的多线程应用程序,我试图将其转换为使用OmniThreadLibrary.我正在使用Virtualtreeview显示日志和状态/结果.Vst Log只有两列,记录只包含两个字符串字段(非常简单,记录中没有对象).
使用OTL附带的DEMO项目(线程池#11)我将项目更改为使用VirtualTreeview而不是列表框.当我从演示中"运行任务"时没有内存泄漏,但是如果我不止一次运行"运行任务",就会发生内存泄漏.如果我多次运行任何任务,将发生内存泄漏.如果我根本不使用VirtualTreeView,则任何时候都不会发生内存泄漏.就在我使用VST和任务运行多次时.
我确实使用FreeNode事件并清除字符串,甚至尝试使用Finalize ...
例:
procedure TFormMain.vstLogFreeNode(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
LogData: PTreeLogData;
begin
LogData:=Sender.GetNodeData(Node);
if Assigned(LogData) then begin
LogData^.Msgtype := '';
LogData^.Msg := '';
end;
//Finalize(LogData^);
end;
Run Code Online (Sandbox Code Playgroud)
当一个任务多次运行时,为什么会出现内存泄漏?Delphi 2010采用FastMM4最新的Virtualtreeview和OTL
我正在创建一个OmniWorker-Task来进行一些数据处理.
到目前为止,该任务能够从/向其他任务接收和发送消息.
现在我需要为这个任务实现main函数.此函数将连续运行并执行数据处理,而消息将修改其行为.
但是我在哪里放这个主要功能?
是否有类似OmniWorker的"执行"方法,我需要实现什么?
我有一个问题,一个简单的TTimer 启动并在主应用程序线程中执行其OnTimer事件,代码如下所示:
procedure TForm1.DoSomeStuff();
begin
OmniLock.Acquire;
try
Parallel.Pipeline.NumTasks(MaxThreads).Stage(StageProc).Run;
if (MyTimer = nil) then
begin
MyTimer := TTimer.Create(nil);
MyTimer.Interval := 60 * 1000; // timer fired every 60 seconds
MyTimer.OnTimer := MyTimerEvent;
MyTimer.Enabled := True;
end;
finally
OmniLock.Release;
end; // try/finally
end;
Run Code Online (Sandbox Code Playgroud)
当我在一个简单的项目/演示中执行代码时,Everthing工作正常,但在我的应用程序(使用Omni Thread Library v3)中,timer事件永远不会被触发
我很确定这没什么,我只是想不通是什么问题!
我检查了三次:MyTimer
在我的代码中只分配了一次,正确分配了OnTimer事件等等...
我正在使用Delphi 2010
谁知道如何解决这个问题?
我最近比较了.NET中的OmniThreadLibrary和ThreadPool,我发现Omni在最大线程中受到更多限制 - 允许60个 - 而.NET 在.NET 4.0中可以达到32768.
为何如此限制?
我已经使用TOmniWorker创建了IOmniTaskControl,以便可以在特定线程中定期运行代码块。因此,我将根据需要在此IOmniTaskControl上调用Invoke。当我这样做时,有时需要等待与该工作相关的执行完成。
我尝试在调用之后在IOmniTaskControl上调用WaitFor(INFINITE),但是它挂起了。我进行了调试,可以看到Invoke调用上的方法已完成。与TOmniWorker一起使用时,我是否误将WaitFor与IOmniTaskControl一起使用?
编辑:我在测试文件夹中编辑了test_43_InvokeAnonymous项目,并且看到了相同的行为:
procedure TfrmInvokeAnonymousDemo.btnInvokeClick(Sender: TObject);
var
formThreadID: DWORD;
task : IOmniTaskControl;
begin
formThreadID := GetCurrentThreadID;
if Sender = btnInvoke then
task := FTask
else
task := FMonitoredTask;
task.Invoke(
procedure (const task: IOmniTask)
var
taskThreadID: DWORD;
begin
// this will execute in the context of the worker thread
taskThreadID := GetCurrentThreadID;
Sleep(2000);
// task.Invoke(
// procedure
// begin
// // this will execute in the context of the main thread
// frmInvokeAnonymousDemo.lbLog.Items.Add(Format(
// 'Current thread ID: %d, task thread ID: …
Run Code Online (Sandbox Code Playgroud) 我的应用程序将有多个任务用于各种操作.
所有任务都在FormCreate中创建并在FormDestroy中终止,只要应用程序正在运行,它们就会一直运行.
主线程的唯一目的是处理用户I/O并将用户输入发送到适当的任务或接收要在主窗体中显示的任务信息.
必须在任务之间传输数据.
示例:
我将执行任务A进行数据处理.
它会将一些结果发送到主线程进行显示.
它还必须将一些(其他)数据发送到任务B,任务B将数据传输到另一台PC.
任务C将从硬件设备接收一些数据,并且必须将此数据发送到任务A进行处理.
等等...
据我所知,到目前为止,使用OmniThreadLibrary发送消息总是在任务和创建任务的线程之间(主线程和任务A,或主线程和任务B).
如何在任意两个任务之间直接发送消息?
或者到目前为止我的方法有什么问题,它应该完全不同吗?
使用OmniThreadLibrary和Delphi XE4,我希望运行多个在后台处理数据的线程,为我现有的代码增加速度.
调用下面的过程时,Application GUI将停止处理任何输入,直到所有线程都完成为止.我的理解是,.NoWait
即使线程正在运行,using也应允许该过程退出.
procedure Test(input: TStringList; output: TList<TMaintFore>);
var
outQueue: IOmniBlockingCollection;
transaction: TOmniValue;
begin
outQueue := TOmniBlockingCollection.Create;
Parallel.ForEach(0, input.Count - 1)
.NoWait
.Into(outQueue)
.Execute(
procedure(const value: integer; var result: TOmniValue)
begin
result := TMaintFore.Create(input[value]);
end
);
end;
Run Code Online (Sandbox Code Playgroud)
我对ForEach循环的理解是否不正确,建议我应该使用替代方法来实现后台处理?任何关于正确使用OmniThreadLibrary的建议都表示赞赏.
我想在我正在使用 Delphi XE2 的项目中使用 OmniThreadLibrary,我已按照说明进行操作。
说明非常简单,OmniEventMonitor 位于调色板中。
但是,我无法运行单个示例。
例如,当我尝试运行时:
procedure TForm2.Button1Click(Sender: TObject);
begin
Button1.Enabled := false;
Parallel.Async(
procedure
begin
// executed in background thread
Sleep(500);
MessageBeep($FFFFFFFF);
end,
Parallel.TaskConfig.OnTerminated(
procedure (const task: IOmniTaskControl)
begin
// executed in main thread
btnAsync.Enabled := true;
end
)
);
end;
Run Code Online (Sandbox Code Playgroud)
我收到错误Undeclared Identifier Parallel。
我在安装过程中做错了什么吗?
我试图从另一个单元/类调用一个函数,这将花费一些时间来执行任务并返回一个字符串值.我找不到类似于C#async的好引用 - 等待Delphi中的简单方法.使用Omni Thread库对我来说似乎是一个好主意.
一个简单的例子对我来说是一个很好的开始.
样本方法:
procedure TForm1.button1Click(Sender: TObject);
begin
// notify before starting the task
memo1.Lines.Add('calling a asynchronous function..');
// call to the function that takes some time and returns a string value
memo1.Lines.Add(GetMagicString);
// notify that the task has been completed
memo1.Lines.Add('Results fetched successfully.');
end;
Run Code Online (Sandbox Code Playgroud)
这里,函数GetMagicString应该异步处理结果.获得结果后,程序才会通知任务已完成.顺便说一下,我正在使用Delphi-XE.
编辑1:这是我试过的.但我仍然无法找到完成工作的正确方法.问题是如何返回值.
.....
private
ResultValue: IOmniFuture<string>;
.........
.....
function TForm1.FutureGet: string;
begin
Sleep(3000);
Result := 'my sample magic string response ' + IntToStr(Random(9999));
end;
procedure TForm1.FutureGetTerminated;
begin
// This code fired …
Run Code Online (Sandbox Code Playgroud) delphi multithreading asynchronous delphi-xe omnithreadlibrary
我希望主应用程序线程能够暂停/恢复其他工作线程,假设这是可能的,最好的方法是什么?
任何适用于Windows XP(及更高版本)的建议都非常受欢迎!
PS.我正在使用Delphi 2010和OmniThreadLibrary 3
我有一个Windows Delphi应用程序,通过通知图标可以访问"开始"和"停止"菜单项.点击"开始"后,我需要执行以下操作(我看到实现):
ThreadMonitor:第一个线程正在等待指定文件夹中指定文件的出现.
ThreadParse:一旦文件出现,它应该被转移到另一个线程(用于解析内容)并继续监视下一个文件.
ThreadDB:解析完所有数据后,将它们保存到MySQL DB中.(具有活动数据库连接的另一个后台线程?)
ThreadLog:如果步骤1-3中有任何错误,请将它们写入日志文件(另一个后台线程?)而不中断步骤1-3.
也就是说,事实证明,像连续输送机这样的东西只能通过按下Stop来停止工作.我应该从OmniThreadLibrary的各种方法中使用什么?
我目前正在尝试使用OmniThreadLibrary.随函附上我的代码:
procedure TMainForm.LongWait;
begin
Task := Parallel.Future<string>(
function: string
begin
Sleep(10000);
Result := 'Done';
end,
Parallel.TaskConfig.OnTerminated(
procedure
begin
if Task.IsDone then
MessageDlg('Complete', mtInformation, [mbOK], 0)
else
MessageDlg('Exception', mtError, [mbCancel], 0)
end)
);
end;
Run Code Online (Sandbox Code Playgroud)
我会调用LongWait(),它可以正常工作而不会阻止UI.我想做的是:
有可能做一个非阻塞功能,可以做所有这些吗?
先感谢您,
V.
编辑:添加问题
delphi ×12
delphi-xe2 ×2
asynchronous ×1
delphi-2009 ×1
delphi-2010 ×1
delphi-xe ×1
delphi-xe4 ×1
delphi-xe5 ×1
resume ×1
timer ×1
vcl ×1