首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >BeginThread Structure - Delphi

BeginThread Structure - Delphi
EN

Stack Overflow用户
提问于 2011-01-25 09:05:16
回答 1查看 5.3K关注 0票数 6

我现在已经有了一个几乎完成的应用程序,我想要实现的下一个功能是线程。我选择使用BeginThread(),尽管我知道Delphi语言中有TThread。我遇到的问题是BeginThread()调用的结构。通常,程序中调用我想要线程化的函数的代码行是

代码语言:javascript
运行
复制
CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op);

op是一个整数。

我把它换成用来创建线程的代码行是

代码语言:javascript
运行
复制
BeginThread(nil,0,CompareFiles,Addr('form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op'),0,x);

从少量的信息中,我可以找到如何实际使用BeginThread()这应该是一个很好的调用,但是在编译时,我得到的是关于我的BeginThread()语句参数结构的编译器错误。

编辑以获取信息。

当前调用CompareFiles的过程是

代码语言:javascript
运行
复制
procedure TForm1.Panel29Click(Sender: TObject);
var
op,x : integer;

begin
    if (Form1.Edit3.Text <> '') AND (Form1.Edit4.Text <> '') then
        begin
          op := 3;
          if RadioButton7.Checked = True then op := 0;
          if RadioButton3.Checked = True then op := 1;
          if RadioButton4.Checked = True then op := 2;
          if RadioButton5.Checked = True then op := 3;
          if RadioButton6.Checked = True then op := 4;
          CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op);
        end;
end;

如果我按照几个人的建议使用TThread,如Rob下面所示,我很困惑a)如何将op、edit3/4、4.Text和StringGrid2传递给CompareFiles。从我看到的TThread示例中,我想我应该用TCompareFilesThread.Execute替换上面的代码,并将Panel29Click中的当前代码放到TCompareFilesThread.Create中,然后添加

代码语言:javascript
运行
复制
FEdit3Text := Edit3Text;
FEdit4Text := Edit4Text;
FGrid := Grid;

到这个

代码语言:javascript
运行
复制
FEdit3Text := Form1.Edit3.Text;
FEdit4Text := Form1.Edit4.Text;
FGrid := Form1.StringGrid2;

但我有一种纠缠不休的感觉,这是完全不正确的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-25 10:32:42

这根本不是使用BeginThread的方法。该函数需要一个指向一个参数的函数的指针,但您尝试调用的函数需要四个参数。您为BeginThread提供的一个转发到线程过程的参数是一个字符串,但是您显然希望通过某种魔法将该字符串转换为这些变量所包含的值。

这不是Delphi的工作方式,即使对于那些可以做到这一点的语言来说,通常也不鼓励真正做到这一点。

要将多个参数传递给BeginThread,请使用所需的所有值定义一条记录,并定义一个记录指针:

代码语言:javascript
运行
复制
type
  PCompareFilesParams = ^TCompareFilesParams;
  TCompareFilesParams = record
    Edit3Text,
    Edit4Text: string;
    Grid: TStringGrid;
    Op: Integer;
  end;

更改CompareFiles以接受指向该记录的指针:

代码语言:javascript
运行
复制
function CompareFiles(Params: PCompareFilesParams): Integer;

要启动线程,您需要分配该记录的一个实例并填充其字段:

代码语言:javascript
运行
复制
var
  Params: PCompareFilesParams;
begin
  New(Params);
  Params.Edit3Text := Edit3.Text;
  Params.Edit4Text := Edit4.Text;
  Params.Grid := StringGrid2;
  Params.Op := op;
  BeginThread(nil, 0, @CompareFiles, Params, 0, x);

像这样实现CompareFiles,以便在线程终止之前释放记录:

代码语言:javascript
运行
复制
function CompareFiles(Params: PCompareFilesParams): Integer;
begin
  try
    // <Normal implementation goes here.>
  finally
    Dispose(Params);
  end;
end;

不过,如果只使用TThread,就可以让这一切变得容易得多。你可以让你的子类在它的构造函数中有任意多的参数,这样你就不必为动态分配和释放一个特殊的记录而烦恼了。

代码语言:javascript
运行
复制
type
  TCompareFilesThread = class(TThread)
  private
    FEdit3Text,
    FEdit4Text: string;
    FGrid: TStringGrid;
    FOp: Integer;
    procedure Execute; override;
  public
    constructor Create(const Edit3Text, Edit4Text: string; Grid: TStringGrid; Op: Integer);
    property ReturnValue;
  end;

constructor TCompareFilesThread.Create;
begin
  inherited Create(False);
  FEdit3Text := Edit3Text;
  FEdit4Text := Edit4Text;
  FGrid := Grid;
  FOp := Op;
end;

procedure TCompareFilesThread.Execute;
begin
  ReturnValue := CompareFiles(FEdit3Text, FEdit4Text, FGrid, FOp);
end;

您只需实例化该类并让其运行,而不是调用BeginThread

代码语言:javascript
运行
复制
var
  ThreadRef: TThread;


ThreadRef := TCompareFilesThread.Create(Edit3.Text, Edit4.Text, StringGrid2, Op);

使用线程还有更多的事情要做,比如知道线程何时结束运行,但我认为您已经足够开始使用线程了。不过,最后要注意的一件事是,TStringGrid是一个VCL控件。您不能在您创建的这个新线程中使用它做任何事情(无论您最终如何创建它)。你对网格控件所做的每一件事都需要从主线程完成。使用TThread.SynchronizeTThread.Queue将任何VCL操作转移到主线程上。文件比较线程将等待同步操作完成,但它将继续运行,而不等待队列操作完成。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4788993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档