A717763229 2021-05-26 16:33 采纳率: 0%
浏览 83

Delphi TTask.run 会阻塞界面

Delphi xe10.4 TTask.run 会阻塞界面

找不到原因 运行几十次才出现一次阻塞

unit UTask;

interface
uses
  System.Classes,Vcl.Forms,System.SysUtils,DateUtils,winapi.shellapi,winapi.Windows,

  System.Threading,System.Generics.Collections, System.Generics.Defaults,obj,TURING_TLB,Ualone;
  const
  WM_MSG        =1280;    //通知消息
  WM_UPDATE     =0;       //通知更新
  WM_STOP       =1;       //通知停止
  WM_BACKROLL   =2;       //通知重新运行
  UI_ADD        =0;       //UI增加
  UI_DELEAT     =1;       //UI删除
  UI_UPDATE     =2;       //UI更新

Type
  TaskMsgState=(UI_PARTMSG,TD_UNSTART,TD_ISOVER,TD_STARTING,TD_RUNNING,TD_PAUSEING,TD_PAUSE,TD_RECOVERING,TD_STOPING);
  TTaskMsg=record
    taskNum:integer;//执行的编号
    id:Integer;//序号

  end;

  TMyTask = class(TTask)
  private

    isPause:boolean;      //是否暂停
    MyITask:ITask;// 启动后的句柄
    procedure Execute;
  public
    _TaskMsg: TTaskMsg;
    _body:Pointer;
    ThreadID:Integer;//线程句柄
    iniName:String; //配置文件名字
    constructor Create(TaskMsg: TTaskMsg);
    function Start(): ITask;
    property Pause:Boolean read isPause write isPause;   //是否暂停
    procedure stop;                    //停止
    function readOver():boolean;        //判断是否停止
    procedure noticeOver();  //通知主线程已经完成
    procedure setTask(Task:string);  //设置任务状态
    procedure setTaskMsg(t:TTaskMsg); //重设taskmsg
    procedure post(WParam:integer);      //多线程控制异步通知UI
    procedure send(WParam:integer);      //多线程控制同步通知UI
end;


var
  taskList: TObjectList<TMyTask>;
  tasks: TArray<ITask>;
  dm:Tzai;
  tl:OleVariant;
implementation
uses
  Ubody,Frame;
{ TMyTask }

constructor TMyTask.Create(TaskMsg: TTaskMsg);
begin
  _TaskMsg := TaskMsg;
  Self.isPause:=False;
  Self.iniName:='当前配置';
end;

procedure TMyTask.Execute;
var
  i:Integer;
  temp:Pointer;
begin
	//阻塞的时候并不会执行到此处
  OutputDebugString('-------------------执行体--1----------------------------');
  temp:=@self;
  OutputDebugString('-------------------执行体--2----------------------------');
  Tbody(_body):=Tbody.Create(temp);
  OutputDebugString('-------------------执行体--3----------------------------');
  ThreadID:=GetCurrentThreadID;
  OutputDebugString('-------------------执行体--4----------------------------');
  Tbody(_body).firing;
  Tbody(_body).Free;

end;


procedure TMyTask.noticeOver;
begin
  self.isPause   :=false;
  _TaskMsg.status    :=TD_ISOVER;
  self.post(WM_UPDATE);
end;

procedure TMyTask.post(WParam: integer);
begin
  postmessage(_TaskMsg.msghandle,1280,WParam, _TaskMsg.id);
end;

function TMyTask.readOver: boolean;
begin
  if (self.CurrentTask.Status=TTaskStatus.Completed)
  or (self.CurrentTask.Status=TTaskStatus.Canceled) then
    result:=True
  else
    result:=False;

end;

procedure TMyTask.send(WParam: integer);
begin
  sendmessage(_TaskMsg.msghandle,1280,WParam, _TaskMsg.id);
end;

procedure TMyTask.setTask(Task: string);
begin
  try
    _TaskMsg.task:=task;
    self.post(WM_UPDATE);
  except

  end;
end;

procedure TMyTask.setTaskMsg(t: TTaskMsg);
begin
  Self._TaskMsg:=t;
end;

function TMyTask.Start(): ITask;
begin
  self._TaskMsg.status:=TD_STARTING;
  OutputDebugString('-------------------启动线程--通知主界面开始----------------------------');
  self.post(WM_UPDATE);
  if IsWindow(self._TaskMsg.winHandle)=false then
  begin
    result:=self.MyITask;
    FrmMain.butRefresh.onClick(FrmMain);
    exit;
  end;

  OutputDebugString('-------------------启动线程--运行TTask.run----------------------------');
  self.MyITask:=TTask.Run(Execute);  //就是这里会阻塞界面!!!!!!!!!!!!!!!!!!!!!!!!!!!
  OutputDebugString('-------------------启动线程--运行TTask.run--结束----------------------------');
  Result :=self.MyITask

end;


procedure TMyTask.stop;
begin
  self.isPause:=False;

  if self.MyITask<>nil then
  begin
    OutputDebugString('TTask.CurrentTask 停止');
    self.MyITask.Cancel;
    self._TaskMsg.status:=TD_ISOVER;
    self.post(WM_UPDATE);
  end
  else
    OutputDebugString('TTask.CurrentTask 为空');
end;

end.
  • 写回答

1条回答 默认 最新

  • weixin_47361975 2023-03-23 23:41
    关注

    替换这一行:
    self.MyITask:=TTask.Run(Execute);
    使用这些行:
    TThread.CreateAnonymousThread(Execute).Start;
    Self.MyITask := TTask.CurrentTask;
    这将创建一个匿名线程并启动它。然后,它会将当前任务分配给MyITask您之前正在做的事情。但是,由于线程现在是匿名创建的,因此它不应导致 UI 阻塞。

    评论

报告相同问题?

悬赏问题

  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法