BeginThread结构 - Delphi [英] BeginThread Structure - Delphi

查看:160
本文介绍了BeginThread结构 - Delphi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  CompareFiles(form1.Edit3.Text,Form1 .Edit4.Text,Form1.StringGrid2,op); 

op是一个整数。



我已经将其切换出来创建一个线程的行是

 code> BeginThread(nil,0,CompareFiles,Addr('form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op'),0,x); 

从少量的信息我可以找到如何实际使用BeginThread()这应该是一个好的通话,但是对于所有我所得到的是关于我的BeginThread()语句参数的结构的编译错误。



编辑信息。



调用CompareFiles的当前过程是

  procedure TForm1.Panel29Click (发件人:TObject); 
var
op,x:integer;

begin
if(Form1.Edit3.Text<>'')AND(Form1.Edit4.Text<>'')然后
begin
op = = 3;
如果RadioButton7.Checked = True,那么op:= 0;
if RadioButton3.Checked = True then op:= 1;
如果RadioButton4.Checked = True然后op:= 2;
如果RadioButton5.Checked = True那么op:= 3;
如果RadioButton6.Checked = True,那么op:= 4;
CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op);
结束
结束

如果我按照几个人的建议使用TThread,并且由Rob在下面显示,我感到困惑,我将如何将op,Edit3 / 4.Text和StringGrid2传递给CompareFiles。从TThread的例子猜测我看到我以为我将用 TCompareFilesThread.Execute 替换上面的代码,并将当前代码从Panel29Click放入 TCompareFilesThread.Create 然后添加

  FEdit3Text:= Edit3Text; 
FEdit4Text:= Edit4Text;
FGrid:=网格;

到这个

 code> FEdit3Text:= Form1.Edit3.Text; 
FEdit4Text:= Form1.Edit4.Text;
FGrid:= Form1.StringGrid2;

但是我的这种n叨感觉完全没有了。

解决方案

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



这不是Delphi如何工作,即使是可以这样做的语言,一般都是不鼓励的要实际执行



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

 键入
PCompareFilesParams = ^ TCompareFilesParams;
TCompareFilesParams = record
Edit3Text,
Edit4Text:string;
网格:TStringGrid;
操作:整数;
结束

更改 CompareFiles 接受一个指针记录:

 函数CompareFiles(Params:PCompareFilesParams):Integer; 

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

  var 
参数: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 在线程终止之前将被释放:

 函数CompareFiles(Params:PCompareFilesParams):Integer; 
begin
try
//<正常执行到这里。>
finally
Dispose(Params);
结束
结束

如果您只使用 TThread ,但。您可以使您的后代类在其构造函数中具有所需的参数,因此您不必动摇分配和释放特殊记录。

  type 
TCompareFilesThread = class(TThread)
private
FEdit3Text,
FEdit4Text:string;
FGrid:TStringGrid;
FOp:整数;
程序执行;覆盖
public
构造函数Create(const Edit3Text,Edit4Text:string; Grid:TStringGrid; Op:Integer);
属性ReturnValue;
结束

构造函数TCompareFilesThread.Create;
begin
继承Create(False);
FEdit3Text:= Edit3Text;
FEdit4Text:= Edit4Text;
FGrid:=网格;
FOp:= Op;
结束

程序TCompareFilesThread.Execute;
begin
ReturnValue:= CompareFiles(FEdit3Text,FEdit4Text,FGrid,FOp);
结束

而不是调用 BeginThread ,您只需要实例化该类让它运行:

  var 
ThreadRef:TThread;


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

还有更多的使用线程,例如知道线程何时完成运行,但我认为你有足够开始最后要注意的是, TStringGrid 是一个VCL控件。你不能从你创建的这个新线程中做任何事情(不管你最终如何创建它)。用网格控件进行的操作需要从主线程中完成。使用 TThread.Synchronize TThread.Queue 将任何VCL操作移到主线程上。您的文件比较线程将等待同步操作完成,但它将继续运行,而不等待排队操作完成。


I've got a almost completed app now and the next feature I want to implement is threading. I chose to go with BeginThread(), although am aware of TThread in delphi. The problem I'm coming across is the structure of BeginThread() call. Normally the line in the program that would call the function I want to be threaded is

CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op);

op is a integer.

The line I've switched it out for to create a thread from it is

BeginThread(nil,0,CompareFiles,Addr('form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op'),0,x);

From the little amount of infromation I can find on how to actually use BeginThread() this should be a fine call, however on compling all I get is complier errors regarding the structure of my BeginThread() statement paramenters.

EDIT FOR INFORMATION.

The current procedure that calls CompareFiles is

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;

If I was to use TThread as suggested by a couple of people, and as displayed by Rob below, I'm confused at how a) I would pass op,Edit3/4.Text and StringGrid2 to the CompareFiles. Guessing from the example of TThread I've seen I thought I would replace the code above with TCompareFilesThread.Executeand the put the current code from Panel29Click into TCompareFilesThread.Create and then add

FEdit3Text := Edit3Text;
FEdit4Text := Edit4Text;
FGrid := Grid;

to this

FEdit3Text := Form1.Edit3.Text;
FEdit4Text := Form1.Edit4.Text;
FGrid := Form1.StringGrid2;

But I've got this nagging feeling that is totally off the mark.

解决方案

That's not at all the way to use BeginThread. That function expects a pointer to a function that takes one parameter, but the function you're trying to call wants four. The one parameter you're giving to BeginThread for it to forward to the thread procedure is a string, but you evidently hope that some sort of magic will turn that string of characters into the values that those variables contain.

That's not how Delphi works, and even for the languages that can do something like that, it's generally discouraged to actually do it.

To pass multiple parameters to BeginThread, define a record with all the values you'll need, and also define a record pointer:

type
  PCompareFilesParams = ^TCompareFilesParams;
  TCompareFilesParams = record
    Edit3Text,
    Edit4Text: string;
    Grid: TStringGrid;
    Op: Integer;
  end;

Change CompareFiles to accept a pointer to that record:

function CompareFiles(Params: PCompareFilesParams): Integer;

To start the thread, you'll need to allocate an instance of that record and populate its fields:

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);

Implement CompareFiles like this so that the record will get freed before the thread terminates:

function CompareFiles(Params: PCompareFilesParams): Integer;
begin
  try
    // <Normal implementation goes here.>
  finally
    Dispose(Params);
  end;
end;

You can make it all a lot easier if you just use TThread, though. You can make your descendant class have as many parameters as you want in its constructor, so you don't have to mess around with dynamically allocating and freeing a special record.

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;

Instead of calling BeginThread, you just instantiate the class and let it run:

var
  ThreadRef: TThread;


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

There's more to using threads, such as knowing when the thread has finished running, but I think you have enough to get started. One last thing to beware of, though, is that TStringGrid is a VCL control. You mustn't do anything with it from this new thread you create (regardless of how you end up creating it). Eveything you do with the grid control need to be done from the main thread. Use TThread.Synchronize and TThread.Queue to shift any VCL operations onto the main thread. Your file-comparing thread will wait for the synchronized operation to complete, but it will keep running without waiting for a queued operation to complete.

这篇关于BeginThread结构 - Delphi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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