我用 WaitForSingleObject 调用了一个cmd命令程序,设置了等待3秒
同时我想在这期间用TTimer 模拟一个执行进度但WaitForSingleObject 锁定了当前主线程,无法实现我的功能

很少进行线程编程,请教一下如何?

解决方案 »

  1.   

    你可以单独开一个线程去完成timer的代码
      

  2.   

    也可以不锁,只是运行得到cmd的句柄后,循环判断此句柄是否结束
    循环中间顺便显示执行进度不过,这个进度恐怕是不准的
      

  3.   

    测试了bdmh的方案, 失败
    unit SimulateProcessbar;interface
     uses
       Windows, ExtCtrls, Classes, ComCtrls, Forms, Dialogs;
    type
      TSimulateProcessbar = class
      private
        hThread :THandle;
      public
        constructor Create(AProgressBar: TProgressBar);
        destructor Destroy; override;
        procedure Start(AResidue:Double);
        procedure Stop;
      end;
    var
      FStopValue :Integer;
      FTimer:TTimer;
      FProgressBar: TProgressBar;
    implementation// --> 这里如果没有WaitForSingleObject,可以进入该事件,在WaitForSingleObject等待期间无法进入
    procedure DoOnTimer(Sender: TObject);
    begin
      with FProgressBar do
      begin
        if Position < FStopValue then
          Position := Position + 1
        else
          FTimer.Enabled := False;  
      end;
    end;{线程入口函数}
    function MyThreadFunc(p: Pointer): Integer; stdcall;
    var
      FOnTimer: TNotifyEvent;
    begin
      FTimer := TTimer.Create(nil);
      FTimer.Interval := 500;
      @FOnTimer := @DoOnTimer;
      FTimer.OnTimer := FOnTimer;
      FTimer.Enabled := True;
      Result := 0;
    end;
    { TSimulateProcessbar }
    constructor TSimulateProcessbar.Create(AProgressBar: TProgressBar);
    begin
      FProgressBar := AProgressBar;
      hThread := 0;
    end;destructor TSimulateProcessbar.Destroy;
    begin
      if hThread > 0 then
        CloseHandle(hThread);
      if Assigned(FTimer) then
      begin
        FTimer.Enabled := False;
        FTimer.Free;
      end;
      inherited;
    end;
    procedure TSimulateProcessbar.Start(AResidue:Double);
    var
      ID: DWORD;
    begin
      FStopValue := Round(FProgressBar.Position + (FProgressBar.Max - FProgressBar.Position) * AResidue );
      if hThread = 0 then
        hThread := CreateThread(nil, 0, @MyThreadFunc, nil, CREATE_SUSPENDED, ID);
      ResumeThread(hThread);
    end;procedure TSimulateProcessbar.Stop;
    begin
      SuspendThread(hThread);
      if Assigned(FTimer) then
      begin
        if FTimer.Enabled then
          FTimer.Enabled := False;
        with FProgressBar do
        if Position < FStopValue then
           Position := FStopValue;
        FTimer.Free;
      end;
      FTimer := nil;
    end;end.
      

  4.   

    lhylhy的方案,放在线程里执行WaitForSingleObject,听起来就复杂了,是新线程在等待还是主线程在等待呢?sz_haitao 说的,不理解你的意思。谁得到的句柄谁负责关闭,循环能判断什么?
      

  5.   

    搞定了,设置了一下新线程的优先级procedure TSimulateProcessbar.Start(AResidue:Double);
    var
      ID: DWORD;
    begin
      FStopValue := Round(FProgressBar.Position + (FProgressBar.Max - FProgressBar.Position) * AResidue );
      if hThread = 0 then
      begin
        hThread := CreateThread(nil, 0, @MyThreadFunc, nil, CREATE_SUSPENDED, ID);
        SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); // 设置优先级为最高
      end;
      ResumeThread(hThread);
    end;
      

  6.   


    主程序只是根据cmd进程id,不断判断它是不是运行完了