相关疑难解决方法(0)

使用Delphi掌握多线程需要哪些核心原则?

我对编程很新(大约8个月在Delphi中打开和关闭,在这里和那里有一点点Python)我正在购买一些书籍.

我有兴趣学习并发编程和使用Delphi构建多线程应用程序.每当我搜索"多线程Delphi"或"Delphi多线程教程"时,我似乎都会得到相互矛盾的结果,因为有些东西是关于使用某些库(Omnithread库)而其他东西似乎更适合具有更多经验的程序员.

我已经研究了很多关于德尔福的书籍,并且在很大程度上它们似乎有点撇开表面并且没有真正深入研究这个主题.我有一个程序员(他使用c ++)的朋友,他建议我在使用线程时学习底层系统的实际情况,而不是首先在我的程序中跳转到如何实际实现它们.

在Amazon.com上有很多关于并发编程的书籍,但似乎没有一本书是用Delphi制作的.

基本上我需要知道在开始使用线程之前我应该​​专注于学习的主要内容,如果我能够/应该尝试使用并非专门针对Delphi开发人员的书籍来学习它们(不想混淆自己阅读现在有很多其他语言代码示例的书籍,如果有关于这个主题的任何可靠的资源/书籍,这里的任何人都可以推荐.

delphi multithreading

15
推荐指数
3
解决办法
3053
查看次数

Delphi多线程消息循环

我的应用程序有几个线程:1)主线程2)2个子主线程(每个都有消息循环,如下所示),由TFQM使用3)n工作线程(简单循环,包含Sleep())

我的问题是,当我关闭我的应用程序时,工作线程设法正常退出,但当我发出WM_QUIT关闭它们时,2个子主线程中的一个挂起(从不退出).


procedure ThreadProcFQM(P: Integer); stdcall;
var
  Msg: TMsg;
 _FQM: TFQM;
begin
  _FQM := Ptr(P);
  try
    _FQM.fHandle := AllocateHwnd(_FQM.WndProc);

    while GetMessage(Msg, 0, 0, 0) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;

  finally
    DeallocateHWnd(_FQM.fHandle);
    SetEvent(_FQM.hTerminated);
  end;
end;
Run Code Online (Sandbox Code Playgroud)
procedure TFQM.Stop;
begin
  PostMessage(fHandle, WM_QUIT, 0, 0);

  WaitForSingleObject(hTerminated, INFINITE);
  if hThread <> INVALID_HANDLE_VALUE then
  begin
    CloseHandle(hThread);
    hThread := INVALID_HANDLE_VALUE;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

delphi winapi multithreading

8
推荐指数
3
解决办法
1万
查看次数

如何从Delphi中的主线程向TThread发送消息?

我想向一个线程发送一条消息并在线程中处理它.我怎么能在Delphi中这样做?我想PostMessage是要走的路,但到目前为止我看到的例子正在描述另一种方式,即从线程到主线程.

delphi multithreading

8
推荐指数
2
解决办法
8236
查看次数

如何让SQL查询线程启动,然后在获得结果之前做其他工作?

我有一个程序,它执行有限形式的多线程.它是用Delphi编写的,使用libmysql.dll(C API)来访问MySQL服务器.该程序必须处理一长串记录,每条记录约0.1秒.把它想象成一个大循环.所有数据库访问都由工作线程完成,工作线程预取下一条记录或写入结果,因此主线程不必等待.

在这个循环的顶部,我们首先等待预取线程,获取结果,然后让预取线程执行下一条记录的查询.想法是预取线程将立即发送查询,并在主线程完成循环时等待结果.

它通常以这种方式工作.但请注意,没有什么可以确保预取线程立即运行.我发现在主线程循环并开始等待预取之前,通常不会发送查询.

我通过在启动预取线程后立即调用sleep(0)来解决这个问题.这样主线程就会放弃它的剩余时间片,希望预取线程现在可以运行,发送查询.然后线程将在等待时休眠,这允许主线程再次运行.
当然,在操作系统中运行了更多的线程,但这确实在某种程度上起作用.

我真正想要发生的是主线程发送查询,然后让工作线程等待结果.使用libmysql.dll我打电话

result := mysql_query(p.SqlCon,pChar(p.query));
Run Code Online (Sandbox Code Playgroud)

在工作线程中.相反,我想让主线程调用类似的东西

mysql_threadedquery(p.SqlCon,pChar(p.query),thread);
Run Code Online (Sandbox Code Playgroud)

一旦数据消失,它将立即切换任务.

有谁知道这样的事吗?

这实际上是一个调度问题,所以我可以尝试以更高的优先级启动预取线程,然后在发送查询后降低其优先级.但同样,我没有任何mysql调用将发送查询与接收结果分开.

也许它在那里,我只是不知道它.请赐教.

补充问题:

有没有人认为通过以比主线程更高的优先级运行预取线程来解决这个问题?这个想法是预取将立即抢占主线程并发送查询.然后它会等待服务器回复.同时主线程将运行.

补充:当前实施的细节

该程序对MySQL DB中包含的数据执行计算.每秒有33M项目添加更多.该程序持续运行,处理新项目,有时重新分析旧项目.它从表中获取要分析的项目列表,因此在传递开始时(当前项目),它知道它将需要的下一个项目ID.

由于每个项目都是独立的,因此这是多处理的完美目标.最简单的方法是在多台计算机上运行多个程序实例.该程序通过分析,重写和算法重新设计进行了高度优化.不过,单个实例在没有数据缺乏的情况下使用100%的CPU核心.我在两个四核工作站上运行4-8份.但按照这个速度,他们必须花时间等待MySQL服务器.(优化服务器/数据库架构是另一个主题.)

我在这个过程中实现了多线程,以避免阻塞SQL调用.这就是我称之为"有限多线程"的原因.工作线程有一个任务:发送命令并等待结果.(好的,两个任务.)

事实证明,有6个阻止任务与6个表相关联.其中两个读取数据,另外四个写入结果.这些类似于足以由公共任务结构定义.指向此Task的指针被传递给线程池管理器,该管理器分配一个线程来完成工作.主线程可以通过Task结构检查任务状态.

这使得主线程代码非常简单.当它需要执行Task1时,它等待Task1不忙,将SQL命令放在Task1中并将其关闭.当Task1不再忙时,它包含结果(如果有的话).

写结果的4个任务是微不足道的.主线程有一个Task写入记录,然后继续下一个项目.完成该项后,它会确保先前的写入在启动另一个之前完成.

2个阅读线程不那么简单.将读取传递给线程然后等待结果将不会获得任何结果.相反,这些任务预取下一个项目的数据.因此,进入此阻塞任务的主线程检查预取是否已完成; 如果需要等待预取完成,则从任务中获取数据.最后,它使用NEXT Item ID重新发出Task.

想法是让预取任务立即发出查询并等待MySQL服务器.然后主线程可以处理当前项目,并且当它在下一个项目上启动时,它需要的数据位于预取任务中.

因此,线程,线程池,同步,数据结构等都已完成.这一切都有效.我剩下的是一个调度问题.

调度问题是这样的:当服务器获取下一个项目时,所有速度增益都在处理当前项目.我们在处理当前项目之前发出预取任务,但我们如何保证它的启动?操作系统调度程序不知道预取任务立即发出查询很重要,然后它只会等待.

OS调度程序正在尝试"公平"并允许每个任务针对指定的时间片运行.我最糟糕的情况是:主线程接收其切片并发出预取,然后完成当前项目并且必须等待下一个项目.等待释放其剩余的时间片,因此调度程序启动预取线程,该线程发出查询然后等待.现在两个线程都在等待.当服务器发出查询信号时,预取线程重新启动,并请求结果(数据集)然后休眠.当服务器提供预取线程唤醒的结果时,标记任务完成并终止.最后,主线程重新启动并从完成的Task获取数据.

为了避免这种最坏情况的调度,我需要一些方法来确保在主线程继续使用当前项之前发出预取查询.到目前为止,我已经想到了三种方法:

  1. 发出预取任务后,主线程调用Sleep(0).这应该放弃剩下的时间片.然后我希望调度程序运行预取线程,它将发出查询然后等待.然后调度程序应该重新启动主线程(我希望.)听起来很糟糕,这实际上比没有好.

  2. 我可能会以比主线程更高的优先级发出预取线程.这应该导致调度程序立即运行它,即使它必须抢占主线程.它也可能有不良影响.后台工作线程获得更高优先级似乎不自然.

  3. 我可以异步发出查询.也就是说,单独发送查询以接收结果.这样我就可以让主线程使用mysql_send_query(非阻塞)发送预取并继续使用当前项.然后,当它需要下一个项目时,它将调用mysql_read_query,它将阻塞直到数据可用.

请注意,解决方案3甚至不使用工作线程.这看起来是最好的答案,但需要重写一些低级代码.我目前正在寻找这种异步客户端 - 服务器访问的示例.

我也喜欢这些方法的任何经验丰富的意见.我错过了什么,或者我做错了什么?请注意,这是所有正常工作的代码.我不是问怎么做,而是如何做得更好/更快.

mysql delphi multithreading scheduling

6
推荐指数
1
解决办法
2386
查看次数

标签 统计

delphi ×4

multithreading ×4

mysql ×1

scheduling ×1

winapi ×1