简体   繁体   English

多线程Delphi Stop

[英]Multiple Thread Delphi Stop

I have a frame, inside it I have a thread, the creation of this front and at runtime, each click that give the button it creates a new frame and may have innumerable within the form. 我有一个框架,在其中有一个线程,创建了这个前端,并且在运行时,每次单击按钮都会创建一个新框架,并且表单中可能有无数个框架。 the problem is that ... I create the first, the thread starts normal when I create the second, the first thread to, and the second begins, if I click again, the first and second stand still and the third begins, if I close the third, the second back to work, because this happens? 问题是...我创建了第一个线程,当我创建了第二个线程时,线程开始正常启动,第一个线程创建了线程,第二个线程开始了,如果再次单击,则第一个和第二个线程保持静止,而第三个线程开始了,如果我关闭第三个,第二个重新工作,因为这种情况发生了吗? thank you 谢谢

constructor TMy_Thread.Create(fraConnect : TfraConnect);
begin
  inherited Create(True);
  Priority        := tpTimeCritical;
  FreeOnTerminate := true;
  fraConnectT     := fraConnect;
end;

procedure TMy_Thread.Execute;
begin
  Synchronize(Teste);
end;

procedure TMy_Thread.TEste;
var
  iSize : Int64;
  iCnt  : Integer;
  Msg : TMsg ;
begin
  inherited;
  with fraConnectT do begin
    While not Terminated do begin
      Log(fraConnectT.Name,'');
      Application.ProcessMessages;
    end;
  end;
end;


////////////////

procedure TfraConnect.Click(Sender: TObject);
var
  Sc : TMy_Thread;
begin
  Sc                    := TMy_Thread.Create(Self);
  try
    iTela            := 0;
    Sc.Execute;
  finally
    Sc.Terminate;
  end;
end;

You are not using TThread correctly. 您没有正确使用TThread You are not starting the thread (so it does not free itself when terminated), you are calling Execute() directly, you are Synchronize ing the entire body of Execute() . 您没有启动线程(因此在终止时它不会释放自身),您在直接调用Execute() ,正在Synchronize Execute()的整个主体。 So Execute() runs in the main thread, calling ProcessMessages() to allow a new button click, which calls Execute() blocking the previous Execute() until the new Execute() exits, and so on. 因此Execute()在主线程中运行,调用ProcessMessages()以允许新的按钮单击,这将调用Execute()阻止以前的Execute()直到新的Execute()退出,依此类推。 That is why you are experiencing the symptoms you are seeing. 这就是为什么您遇到的症状。

To fix this, you need to do the following: 要解决此问题,您需要执行以下操作:

  • In the thread constructor, call inherited Create(False) instead. 在线程构造函数中,改为调用inherited Create(False) This allows the thread to start running automatically. 这允许线程自动开始运行。 Otherwise, you have to call the thread's Resume() or Start() method after the constructor exits. 否则,您必须在构造函数退出后调用线程的Resume()Start()方法。

  • remove Execute() from Click() . Click()删除Execute() Click() Let the running thread call Execute() . 让正在运行的线程调用Execute()

  • remove ProcessMessages() from Teste() . Teste()删除ProcessMessages() Teste() There is never a need to call ProcessMessages() in a thread (unless it is being called inside of Synchronize d or Queue d code running in the main thread, but even then it should be avoided when possible). 永远不需要在线程中调用ProcessMessages() (除非在主线程中运行的Synchronize d或Queue d代码内部调用它,但即使在可能的情况下,也应避免使用它)。

  • only Synchronize() small code blocks that actually need to run in the main thread - code that does not work in a secondary thread, code that needs to access the UI, code that needs to access a resource shared by multiple threads, etc. The bulk of your thread code should NOT be Synchronize d, that defeats the purpose of using a thread in the first place. 需要实际在主线程中运行的Synchronize()小代码块-在辅助线程中不起作用的代码,需要访问UI的代码,需要访问由多个线程共享的资源的代码,等等。您的大部分线程代码不应为Synchronize d,这违背了首先使用线程的目的。

Try something more like this: 尝试更多类似这样的方法:

type
  fraConnect = class;
  TMy_Thread = class(TThread)
  private
    fraConnectT : TfraConnect;
    procedure DoLog;
  protected
    procedure Execute; override;
  public
    constructor Create(fraConnect : TfraConnect);
    property Terminated;
  end;

...

constructor TMy_Thread.Create(fraConnect : TfraConnect);
begin
  inherited Create(True);
  Priority        := tpTimeCritical;
  FreeOnTerminate := true;
  fraConnectT     := fraConnect;
end;

procedure TMy_Thread.Execute;
begin
  with fraConnectT do begin
    While not Terminated do begin
      // assuming Log() is not thread-safe...
      Synchronize(DoLog);
      Sleep(100);
    end;
  end;
end;

procedure TMy_Thread.DoLog;
begin
  Log(fraConnectT.Name,'');
end;

type
  TMy_Thread = class;
  TfraConnect = class(TFrame)
    Start: TButton;
    Stop: TButton;
    StartClick(Sender: TObject);
    StopClick(Sender: TObject);
  private
    Sc: TMy_Thread;
    procedure ThreadTerminated(Sender: TObject);
  end;

...

procedure TfraConnect.StartClick(Sender: TObject);
begin
  if (not Assigned(Sc)) or Sc.Terminated then
  begin
    Sc := TMy_Thread.Create(Self);
    Sc.OnTerminate := ThreadTerminated;
    Sc.Resume; // or Sc.Start;
  end;
end;

procedure TfraConnect.StopClick(Sender: TObject);
begin
  if Assigned(Sc) then
    Sc.Terminate;
end;

procedure TfraConnect.ThreadTerminated(Sender: TObject);
begin
  if Sc = Sender then
    Sc := nil;
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM