Delphi TTask从主线程获取数据 [英] Delphi TTask get data from main thread

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

问题描述

根据我对尼克·霍奇斯的理解,这段代码应该没问题:

From what I have understood reading Nick Hodges, this code should be fine:

TTask.Run(
  procedure
  var
    resp, tmp: string;
    req: boolean;
    bwriter: TBinaryWriter;
    myfile: TFileStream;
  begin
    //tell the user to wait
    TThread.Queue(TThread.CurrentThread,
      procedure
      begin
        LoginButton.Text := 'Please wait...';
      end
    );

    //some checks
    try
      resp := GetURL('... here I get a result from the server...');
      if (resp = fOKstatus) then
      begin
        req := true;

        myfile := TFileStream.Create(TPath.Combine(TPath.GetHomePath, 'docs.mkb'), fmCreate);
        try
          bwriter := TBinaryWriter.Create(myfile, TEncoding.Unicode, false);
          try
            bwriter.Write(UsernameEdit.Text);
            bwriter.Write(AppIDEdit.Text);
            bwriter.Close;
          finally
            bwriter.Free;
          end;
        finally
          myfile.Free;
        end;
      end
      else
      begin
        req := false;
      end;
    except
      req := false;
    end;

    //final
    TThread.Queue(TThread.CurrentThread,
      procedure
      begin
        if (req = true) then
        begin
          LoginButton.Text := 'Success!';
          ShowMessage('Close the app to complete the registration.');
        end
        else
        begin
          LoginButton.Text := 'Login failed.';
        end;
      end
    );

  end
);

此代码在单独的线程中运行,并通过对Queue()的调用链接到主线程.实际上,在一开始,我正在使用此方法更新Button的Text.

This runs in a separated thread, and it is linked to the main thread with the calls to Queue(). In fact, at the beginning I am updating the Text of a Button using this method.

问题.看这两行:

bwriter.Write(UsernameEdit.Text);
bwriter.Write(AppIDEdit.Text);

我需要从主线程UI中的两个Edit控件中检索用户名和AppID(这是一个随机代码).这是正确的吗?

I need to retrieve the username and AppID (which is a random code) from two Edit controls that are in the main thread UI. Is this correct?

我想我应该调用Queue(),但是到目前为止该程序运行良好.

I guess that I should call Queue(), but so far the program is working well.

我可以通过这种方式安全地获取值吗?我什么都没有更新,我只需要获取数据,但是我不确定混合来自2个不同任务的内容是否危险/不好.

Can I take the values in this way safely? I am not updating anything, and I just need to grab the data, but I am not sure if mixing contents from 2 different tasks can be dangerous/bad practice.

推荐答案

您关注的两行代码不是线程安全的.您必须与主线程同步,以进行 all UI访问,包括读取和写入. TThread.Queue()异步,因此不适用于从UI检索值的目的.请使用TThread.Synchronize()同步:

The 2 lines of code you are concerned about are NOT thread-safe. You must synchronize with the main thread for all UI access, both reading and writing. TThread.Queue() is asynchronous, so it is not suitable for the purpose of retrieving values from the UI. Use TThread.Synchronize() instead, which is synchronous:

TTask.Run(
  procedure
  var
    resp, tmp, username, appid: string;
    req: boolean;
    bwriter: TBinaryWriter;
    myfile: TFileStream;
  begin
    //tell the user to wait
    TThread.Queue(nil,
      procedure
      begin
        LoginButton.Text := 'Please wait...';
      end
    );

    //some checks
    try
      resp := GetURL('... here I get a result from the server...');
      if resp = fOKstatus then
      begin
        req := true;

        TThread.Synchronize(nil,
          procedure
          begin
            username := UsernameEdit.Text;
            appid := AppIDEdit.Text;
          end
        );

        myfile := TFileStream.Create(TPath.Combine(TPath.GetHomePath, 'docs.mkb'), fmCreate);
        try
          bwriter := TBinaryWriter.Create(myfile, TEncoding.Unicode, false);
          try
            bwriter.Write(username);
            bwriter.Write(appid);
            bwriter.Close;
          finally
            bwriter.Free;
          end;
        finally
          myfile.Free;
        end;
      end
      else
      begin
        req := false;
      end;
    except
      req := false;
    end;

    //final
    TThread.Queue(nil,
      procedure
      begin
        if req then
        begin
          LoginButton.Text := 'Success!';
          ShowMessage('Close the app to complete the registration.');
        end
        else
        begin
          LoginButton.Text := 'Login failed.';
        end;
      end
    );
  end
);

或者,假设主UI线程是启动TTask的线程,则可以在启动TTask之前读取2个值,并让匿名过程捕获它们:

Alternatively, assuming the main UI thread is the one starting the TTask, you can read the 2 values before starting the TTask and let the anonymous procedure capture them:

var
  username, appid: string;
begin
  username := UsernameEdit.Text;
  appid := AppIDEdit.Text;

  TTask.Run(
    procedure
    var
      resp, tmp: string;
      req: boolean;
      bwriter: TBinaryWriter;
      myfile: TFileStream;
    begin
      //tell the user to wait
      TThread.Queue(nil,
        procedure
        begin
          LoginButton.Text := 'Please wait...';
        end
      );

      //some checks
      try
        resp := GetURL('... here I get a result from the server...');
        if resp = fOKstatus then
        begin
          req := true;

          myfile := TFileStream.Create(TPath.Combine(TPath.GetHomePath, 'docs.mkb'), fmCreate);
          try
            bwriter := TBinaryWriter.Create(myfile, TEncoding.Unicode, false);
            try
              bwriter.Write(username);
              bwriter.Write(appid);
              bwriter.Close;
            finally
              bwriter.Free;
            end;
          finally
            myfile.Free;
          end;
        end
        else
        begin
          req := false;
        end;
      except
        req := false;
      end;

      //final
      TThread.Queue(nil,
        procedure
        begin
          if req then
          begin
            LoginButton.Text := 'Success!';
            ShowMessage('Close the app to complete the registration.');
          end
          else
          begin
            LoginButton.Text := 'Login failed.';
          end;
        end
      );
    end
  );
end;

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

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