将数据从TThread发送到主VCL线程 [英] Sending data from TThread to main VCL Thread

查看:78
本文介绍了将数据从TThread发送到主VCL线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一些通过dll与外部硬件通信的软件(移动一些电动机并读回一些值).对该dll的调用被阻止,并且可能在10秒的时间内无法返回.该软件通过移动硬件,进行读取并重复许多点来执行扫描.一次扫描可能需要30分钟才能完成.扫描运行时,我显然希望GUI能够响应并在每个点更新传入数据的实时图形(在MDI Child中).多线程似乎是解决此问题的明显选择.

I'm writing some software that talks to external hardware via a dll (moving some motors and reading some values back). The calls to the dll are blocking and may not return for in the order of 10 seconds. The software performs a scan by moving the hardware, taking a reading and repeating for a number of points. One scan can take in the order of 30 minutes to complete. While the scan is running I would obviously like the GUI to be responsive and a live graph (in an MDI Child) of the incoming data to be updated at each point. Multithreading seems the obvious choice for this problem.

我的问题是,将其线程化并与VCL主线程对话以在扫描期间更新图形的最佳方法是什么?

My question is, what is the best way to thread this and talk back to the main VCL thread to update the graph during a scan?

我目前有一个执行扫描逻辑"的单个TThread后代,以及ChildForm的public var部分中的一个double数组.我需要从线程中填充此数组,但是我不知道是否要使用Synchronize或CriticalSection或PostMessage或其他方法.每次添加新值时,主VCL线程都需要更新图形.我是否真的应该为全局变量的数据提供一个中间对象,并以某种方式分别从Thread和ChildForm进行访问?

I currently have a single TThread descendant that performs the 'scan logic' and an array of doubles in the public var section of the ChildForm. I need to fill out this array from the thread but I don't know whether to use Synchronize or CriticalSection or PostMessage or some other method. Each time a new value is added, the main VCL thread needs to update the graph. Should I really have an intermediary object for the data that is a global var and access this from the Thread and the ChildForm separately somehow?

推荐答案

从线程更新GUI的最简单方法是使用 TThread.Synchronize TThread.Queue .

The simplest way to update the GUI from a thread is to use anonymous methods in conjunction with TThread.Synchronize and TThread.Queue.

procedure TMyThread.Execute;
begin
  ...
  Synchronize(  // Synchronous example
    procedure
    begin
      // Your code executed in main thread here 
    end
  );
  ...
  Queue( // Asynchronous example
    procedure
    begin
      // Your code executed in main thread here
    end
  );
end;

传递值异步通常需要捕获"一个值.

Passing values asynchronous often requires "capturing" a value.

procedure TMyThread.PassAValue(anInteger: Integer);
begin
  Queue(
    procedure
    begin
      // Use anInteger in main thread 
    end
  );
end;

procedure TMyThread.Execute;
var
  myInt: Integer;
begin
  ...
  PassAValue(myInt);  // Capture myInt
  ...
end;

当匿名方法使用变量时,将捕获对变量的引用. 这意味着,如果您在执行匿名方法之前更改了变量值,则将使用新值.因此,需要捕获值".

When an anonymous method is using a variable, the reference to the variable is captured. This means that if you alter the variable value before the anonymous method is executed, the new value is used instead. Hence the need to capture the "value".

可以在此处找到更详细的示例, @UweRaabe .

A more elaborate example can be found here, synchronize-and-queue-with-parameters, by @UweRaabe.

这篇关于将数据从TThread发送到主VCL线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆