【问题标题】:Sleeping thread and thread initialization inside constructor构造函数内的休眠线程和线程初始化
【发布时间】:2014-08-13 14:02:05
【问题描述】:

我试图让一个线程用完一个 ctor ,线程应该休眠,唤醒,然后执行缓冲区转储,然后再次休眠,依此类推,这是 ctor 的代码:

 Logger::Logger()
 {
   BufferInUse = &CyclicBuffer1;                        //buffer 1 will be used at    beggining
   MaxBufferSize = 5;                                   //initial state
   NumOfCycles = 0;
   CurrentMaxStringLength = 0;

   position = BufferInUse->end();
   OutPutMethod = odBuffer;                         //by default
   Thresh = 1;                                      //by default

   hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
   EventTime.QuadPart = -20000000;                          //1 second by default
   Mutex =  CreateMutex(NULL,FALSE,NULL);   
   if (Mutex == NULL) 
   { 
       OutputDebugStringA("CreateMutex error! the Logger will close \n");
       return ;
   }
   _beginthread( Logger::WorkerThread , 0,(void*)this );    //run the thread
}

当我调试它时,甚至需要花费大量时间来创建线程并完成 ctor 函数,但那时我的对象成员函数被调用了很多次(我在调试时看到它)。 1.我希望在调用我的成员函数之前创建线程,实现这一目标的最佳方法是什么?

现在我的线程实现是:

               void Logger::WorkerThread ( void *lpParam )
              {
                   Logger *log = static_cast <Logger*> (lpParam);
                   if (NULL == log->hTimer)
                   {
                      log->LogStringToOutput("CreateWaitableTimer() failed , Logger will close \n");
                       return;
                    }

               for(;;)
               {
                 //set timer for time specified by the EventTime variable inside the Logger
                 if (!SetWaitableTimer(log->hTimer, & (log->EventTime), 0, NULL, NULL, 0))
                 {
                     log->LogStringToOutput("SetWaitableTimer() failed , Logger will close\n" );
                    _endthread();
                 }

               //wait for timer
              if (WaitForSingleObject(log->hTimer, INFINITE) != WAIT_OBJECT_0)
              {
                   log->LogStringToOutput("WaitForSingleObject() failed! Logger will close\n");
                  _endthread();
                  return;
              }

              if(log->getOutputMethod() == odBuffer && log->BufferInUse->size() >= log->Thresh && !log->BufferInUse->empty())
              {
                  TTFW_LogRet ret;
                 ret = log->FullBufferDump();
                 if (ret != SUCCESS)
                 {
                       log->LogStringToOutput("Error occured in dumping cyclic buffer , the buffer will be cleared\n");
                 }
             }
           }

        }

这个线程功能有更优雅的实现吗?

【问题讨论】:

  • 你真的应该使用std::threadstd::mutexstd::this_thread
  • 我不能,因为我只有 VS 2008 并且没有更新版本的许可证,所以我无法实现 c++11 功能
  • C++11 是 C++。您标记了您的问题 C++,而不是 C++03。我添加了 C++03 标记,以表明您不愿意或无法使用所有 C++。

标签: c++ multithreading c++03


【解决方案1】:

你需要一些机制来同步 WorkerThread 的启动和成员函数的访问。

例如,使用条件变量(documents in msdn):

向 Logger 添加 3 个成员:

class Logger{
...

private:        
    CRITICAL_SECTION CritSection;
    CONDITION_VARIABLE ConditionVar;
    bool WorkerThreadStarted;

...
};

 Logger::Logger():WorkerThreadStarted(false)
 {
     EnterCriticalSection(&CritSection); //added

     BufferInUse = &CyclicBuffer1;    //buffer 1 will be used at    beggining

     ...
  }

 void Logger::WorkerThread ( void *lpParam )
 {

     WorkerThreadStarted=true; //added
     LeaveCriticalSection(&CritSection);

     Logger *log = static_cast <Logger*> (lpParam);
     if (NULL == log->hTimer)
     {
        log->LogStringToOutput("CreateWaitableTimer() failed , Logger will close \n");
         return;
     }


     ...
}

添加这样的功能:

  void Logger::EnsureInitiallized(){

      EnterCriticalSection(&CritSection);

      // Wait until the predicate is TRUE

      while( !WorkerThreadStarted )
      {
         SleepConditionVariableCS(&ConditionVar, &CritSection, INFINITE);
      }

      LeaveCriticalSection(&CritSection);
  }

在每个成员函数的入口处,调用 EnsureInitiallized();

  void Logger::yourFunction(){
    EnsureInitiallized();

    ...
  }

这是一个例子,你也可以使用读写锁、原子整数等

【讨论】:

  • 这似乎是一个合理的解决方案,但它不起作用,程序卡在 SleepConditionVariableCS(&ConditionVar, &CritSection, INFINITE);线,它永远保持这种状态
  • 哦,我弄错了,在WorkerThread中,在LeaveCriticalSection之前,不应该调用Logger的成员函数,这样会导致自死锁。我在上面更正了。
  • 几乎是真的,WorkerThread 是一个静态函数,所以我向函数传递了一个指向对象的指针,这样我就可以访问它的成员,如果你将成员声明为类的私有成员,你就不能访问它们在获得 this 指针之前,您应该在开始时进行强制转换,然后 WorkerThreadStarted=true; //添加 LeaveCriticalSection(&CritSection);或者可能将这些变量声明为静态类成员...
猜你喜欢
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2019-11-21
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多