Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 终止线程变量并将其设置为NULL_Multithreading_C++builder_Tthread - Fatal编程技术网

Multithreading 终止线程变量并将其设置为NULL

Multithreading 终止线程变量并将其设置为NULL,multithreading,c++builder,tthread,Multithreading,C++builder,Tthread,使用TThread子代时,我基本上有一个选择: 将FreeOnTerminate设置为true,删除我的TThread子体对象,但不将其设置为NULL 手动操作,然后亲自完成移除的所有步骤 我基本上需要的是一种确定线程是否正在运行的方法,因此我执行了以下操作: //------------------------------------------------------------------------------ // Thread descendant //-------------

使用
TThread
子代时,我基本上有一个选择:

  • FreeOnTerminate
    设置为
    true
    ,删除我的
    TThread
    子体对象,但不将其设置为
    NULL
  • 手动操作,然后亲自完成移除的所有步骤
我基本上需要的是一种确定线程是否正在运行的方法,因此我执行了以下操作:

//------------------------------------------------------------------------------
// Thread descendant
//------------------------------------------------------------------------------
class TMyThread : public TThread
    {
    private:   UnicodeString StatusLine;  // Used for Synchronize function

               void __fastcall UpdateGUI();
    protected: virtual void __fastcall Execute();
    public:                 __fastcall TMyThread();
    };
//------------------------------------------------------------------------------
TMyThread *MyThread;
//------------------------------------------------------------------------------

// Thread constructor
__fastcall TMyThread::TMyThread() : TThread(true)
{
FreeOnTerminate = false;
Priority        = tpNormal;
}

 // Synchronize function for Form1
void __fastcall TMyThread::UpdateGUI()
{
Form1->Label1 = StatusLine; 
}

// Execute code
void __fastcall TMyThread::Execute()
{
Sleep(2000);
StatusLine = "I am almost done!";
Synchronize(&UpdateGUI);
}

// Thread terminate, delete object, set to NULL
void __fastcall TForm1::ThreadTerminateIfDone(TMyThread *T)
{
if (T != NULL && WaitForSingleObject(reinterpret_cast<void*>(T->Handle),0) == WAIT_OBJECT_0)
    {
    T->Terminate();
    T->WaitFor();
    delete T;
    T = NULL;
    }
}

// And initialization part which needs to check if thread is already running
void __fastcall TForm1::StartOrRestartThread(TObject *Sender)
{
// Remove old thread if done
ThreadTerminateIfDone(MyThread);

// Check if thread is running - NULL = not running and terminated or uninitialized
if (MyThread == NULL)
    {
    MyThread = new TMyThread();
    MyThread->Start();
    }
else
    {
    Application->MessageBox(L"Thread is still running please wait!", L"Error", MB_OK);
    }
}
//------------------------------------------------------------------------------
//线程后代
//------------------------------------------------------------------------------
类TMyThread:publictthread
{
private:UnicodeString StatusLine;//用于同步功能
void uu fastcall UpdateGUI();
受保护:虚拟void_uufastcall Execute();
public:_fastcall TMyThread();
};
//------------------------------------------------------------------------------
TMyThread*MyThread;
//------------------------------------------------------------------------------
//线程构造函数
__快速调用TMyThread::TMyThread():TThread(true)
{
FreeOnTerminate=false;
优先级=tpNormal;
}
//Form1的同步功能
void uu fastcall TMyThread::UpdateGUI()
{
Form1->Label1=状态行;
}
//执行代码
void uu fastcall TMyThread::Execute()
{
睡眠(2000年);
StatusLine=“我几乎完成了!”;
同步(&UpdateGUI);
}
//线程终止,删除对象,设置为NULL
void _fastcall TForm1::ThreadTerminateIfDone(TMyThread*T)
{
如果(T!=NULL&&WaitForSingleObject(重新解释强制转换(T->Handle),0)=WAIT\u OBJECT\u 0)
{
T->Terminate();
T->WaitFor();
删除T;
T=零;
}
}
//初始化部分,需要检查线程是否已经运行
void _fastcall TForm1::StartOrRestartThread(TObject*发送方)
{
//如果完成,请移除旧螺纹
螺纹端接FDONE(MyThread);
//检查线程是否正在运行-NULL=未运行且已终止或未初始化
if(MyThread==NULL)
{
MyThread=新的TMyThread();
MyThread->Start();
}
其他的
{
应用程序->消息框(L“线程仍在运行,请稍候!”,L“错误”,MB_OK);
}
}
此代码按原样工作。我的问题是:

  • 有没有办法简化这一点?完成后,我需要将
    MyThread
    设置为NULL,以便在下次调用start/restart之前对象不存在?如果将
    FreeOnTerminate
    设置为true,则无法执行此操作,因为它会删除对象。我只能尝试访问对象,然后该对象会生成异常(我可以捕获,但它是哑的)。在初始化或重新启动MyThread之前,我只需要知道MyThread是否已执行完毕

  • 我可以在不终止线程的情况下重新启动线程吗(在程序完成之前我不需要删除对象)-如果我启动线程,我会得到“无法在运行或挂起的线程上调用start”异常


    • 在线程中运行while循环,并在顶部进行一些等待,以允许它在收到信号时运行一次,这比持续创建/终止/销毁线程以及相关的微管理更可取,因此没有其他过程是合理的

      创建线程,将其放入一个while循环,在循环的顶部加上一个wait,发出信号让它运行,并且永远不要终止线程,除非绝对强制终止

      死亡召唤:

      TThread.WaitFor
      TThread.Synchronize
      TThread.Terminate
      
      尽量不要用这些,永远不要

      简单的例子:

      TmyThread=class(TThread);
      private;
        mySimpleEvent:TSimpleEvent;
      public
        constructor create;
        procedure go;
      end;
      
      constructor TmyThread.create;
      begin
        inherited create(true);
        mySimpleEvent:=TSimpleEvent.Create;
        resume;
      end;
      
      procedure TmyThread.go;
      begin
        mySimpleEvent.SetEvent;
      end;
      
      procedure TmyThread.Execute;
      begin
        while mySimpleEvent.WaitFor(INFINITE) do
        begin
          mySimpleEvent.ResetEvent;
          //code to do your stuff
        end;
      end;
      

      ThreadTerminateIfDone()
      函数需要通过引用获取线程指针,否则将无法将指针正确设置为NULL:

      void __fastcall TForm1::ThreadTerminateIfDone(TMyThread* &T)
      
      话虽如此,如果使用线程的
      OnTerminate
      事件跟踪线程是否正在运行,则可以完全消除
      ThreadTerminateIfDone()
      。当
      FreeOnTerminate
      设置为true时,将在释放线程之前触发
      OnTerminate
      ,例如:

      class TMyThread : public TThread
      {
      private:
          String StatusLine;  // Used for Synchronize function
          void __fastcall UpdateGUI();
      protected:
          virtual void __fastcall Execute();
      public:
          __fastcall TMyThread();
      };
      //------------------------------------------------------------------------------
      extern TMyThread *MyThread;
      //------------------------------------------------------------------------------
      

      要回答您的另一个问题,如果您希望线程可重启,则必须稍微更改线程设计,例如:

      class TMyThread : public TThread
      {
      private:
          String StatusLine;  // Used for Synchronize function
          TEvent *RestartEvent;
          void __fastcall UpdateGUI();
      protected:
          virtual void __fastcall Execute();
      public:
          bool Busy;
          __fastcall TMyThread();
          __fastcall ~TMyThread();
          void __fastcall Restart();
      };
      //------------------------------------------------------------------------------
      extern TMyThread *MyThread;
      //------------------------------------------------------------------------------
      


      在没有同步的情况下,我应该如何更新VCL?线程是在“一次性”模式下完成的,所以一旦完成它就会自动终止,不需要循环。可以避免创建/删除,但一旦终止,我就无法重新启动它-我得到“无法启动挂起或终止的线程”。有什么想法吗?更新VCL:PostMessageAPI。线程是在“一次性”模式下完成的-停止“一次性”模式,并使用一个在顶部有同步对象等待的循环:事件或信号量。如果这样做,就不需要终止线程,因此也不需要尝试重新启动它——只需向synchro对象发送信号,while循环中的线程代码就会再次执行。只需让线程永远存在(即,直到应用程序终止,操作系统终止为止)。换句话说,你建议让线程使用100%的CPU运行一个空循环,并且只在发出工作信号时才执行操作?我可以将优先级降低到tpIdle,但仍然会使用100%的CPU。对CPU不是很友好。该线程需要连接到服务器,并可能每15分钟获取一次或两次数据。在空闲时间以循环方式运行它是没有意义的!等待内核同步对象-线程在其上阻塞,CPU使用率为0%,直到发出信号。在信号量上使用TEvent.WaitFor、TSimpleEvent.WaitFfor或WaitForSingleObject()。没有CPU密集型循环。好的,我们也会测试它。感谢您提出的好主意和付出的可见努力。我确实尝试过这一点,但您确定我可以在ThreadTerminated事件内部将MyThread设置为NULL吗?如果对象尚未释放,是否会导致访问冲突?@Coder12345:是的,我确定。
      OnTerminate
      事件通过
      Synchronize()
      触发,线程对象将在
      OnTerminate
      事件处理程序退出后才会释放。
      class TMyThread : public TThread
      {
      private:
          String StatusLine;  // Used for Synchronize function
          TEvent *RestartEvent;
          void __fastcall UpdateGUI();
      protected:
          virtual void __fastcall Execute();
      public:
          bool Busy;
          __fastcall TMyThread();
          __fastcall ~TMyThread();
          void __fastcall Restart();
      };
      //------------------------------------------------------------------------------
      extern TMyThread *MyThread;
      //------------------------------------------------------------------------------
      
      TMyThread *MyThread = NULL;
      
      __fastcall TMyThread::TMyThread()
          : TThread(true)
      {
          FreeOnTerminate = true;
          Priority        = tpNormal;
          RestartEvent    = new TEvent(nil, true, true, "");
      }
      
      __fastcall TMyThread::~TMyThread()
      {
          delete RestartEvent;
      }
      
      void __fastcall TMyThread::UpdateGUI()
      {
          Form1->Label1 = StatusLine; 
      }
      
      void __fastcall TMyThread::Execute()
      {
          while (!Terminated)
          {
              if (RestartEvent.WaitFor(1000) == wrSignaled)
              {
                  if (Terminated) return;
      
                  RestartEvent.ResetEvent();
                  Busy = true;
      
                  StatusLine = "I am doing something!";
                  Synchronize(&UpdateGUI);
      
                  Sleep(2000);
      
                  StatusLine = "I am almost done!";
                  Synchronize(&UpdateGUI);
      
                  Busy = false;
              }
          }
      }
      
      void __fastcall TForm1::StartOrRestartThread(TObject *Sender)
      {
          if (MyThread == NULL)
          {
              MyThread = new TMyThread();
              MyThread->OnTerminate = ThreadTerminated;
              MyThread->Start();
          }
          else if (!MyThread->Busy)
          {
              MyThread->Restart();
          }
          else
          {
              Application->MessageBox(L"Thread is still running please wait!", L"Error", MB_OK);
          }
      }
      
      void __fastcall TForm1::ThreadTerminated(TObject *Sender)
      {
          MyThread = NULL;
      }