线程问题,其中一个线程工作,但导致调用方法不返回
Threading issue where 1 thread works but causes the calling method to not return
我目前正在学习c++,我有一个奇怪的问题与线程。我在Java和c#中做了很多线程化的东西,没有遇到过问题。我目前正试图复制一个c#库,我在c++中有一个库和一个测试应用程序。
在main.cpp中,我创建了一个InitialiseLibrary
类的实例,并调用initialise
方法。这将加载配置,然后启动一个线程,该线程在应用程序运行期间保持运行。我期待这个线程开始,然后我的初始化函数返回true,然后我继续,我创建一个测试类的实例,它每1秒写入一个日志文件。
下面是main.cpp
InitialiseLibrary initLibrary("config.ini");
if (!initLibrary.initialise(1))
{
cout << "Failed to initialise library" << endl;
return EXIT_FAILURE;
}
TestClass testClass;
testClass.writeSomeLogsInThread();
cout << "The library config log file is: " << GlobalConfig::GeneralConfig::logFile << endl;
在我的initialize方法(这是在库中),我有:
bool InitialiseLibrary::initialise(int applicationAlarmID, int applicationTerminationTimeout)
{
//statusManager.setApplicationStatus(StatusManager::ApplicationStatus::Starting);
if (!this->loadInconfiguration(applicationAlarmID))
{
cout << "*****Failed to configuration. Cannot continue******" << endl;
return false;
}
GlobalConfig::libraryInitialised = true;
LogRotation logRotation;
logRotation.startLogRotation();
BitsLibrary bitsLibrary;
//Set up the signal handler if its needed, 0 means it terminates instantly, doesn't wait -1 is don't use signal handler
if (applicationTerminationTimeout >= 0)
{
bitsLibrary.setupSignalHandler(applicationTerminationTimeout);
}
return true;
}
如您所见,我读取了配置,然后调用' logroation . startlogroation()。
其中我有以下代码:
void LogRotation::startLogRotation()
{
//Is the configuration successfully loaded
if (!LogRotateConfiguration::configurationLoaded)
{
throw exception("Log Rotation not initialised");
}
BitsLibrary bitsLibrary;
stringstream logStream;
logStream << "Log rotation thread starting, monitor cycle time is " << LogRotateConfiguration::archiveSleepTimeInSeconds << " second(s)";
bitsLibrary.writeToLog(logStream.str(), "LogRotation", "startLogRotation");
thread logRotationThread(&LogRotation::logRotationThread, this);
logRotationThread.join();
}
void LogRotation::logRotationThread()
{
BitsLibrary bitsLibrary;
while (bitsLibrary.getApplicationStatus() == StatusManager::ApplicationStatus::Starting || bitsLibrary.getApplicationStatus() == StatusManager::ApplicationStatus::Running)
{
bitsLibrary.writeToLog("Running log monitoring");
this_thread::sleep_for(chrono::seconds(LogRotateConfiguration::archiveSleepTimeInSeconds));
}
stringstream logStream;
logStream << "Log rotation archive monitoring stopped. Current application status: " << bitsLibrary.getApplicationStatus();
bitsLibrary.writeToLog(logStream.str(), "LogRotation", "logRotationThread");
}
在这里,我期待,startLogRotation()
开始运行一个线程内的方法logRotationThread
,线程启动,startLogrotation()方法完成并通过堆栈返回initialize()方法,返回true,回到main,然后我可以在线程内调用我的TestClass方法。
出于某种原因,虽然,线程开始并保持日志记录每隔几秒钟Running log monitoring
所以我知道线程已经开始,但它似乎没有返回到初始化函数返回true,所以应用程序卡住了那个函数调用,不走得更远。
我读到你需要在线程上运行join
以保持它与主线程同步,否则主线程退出,而新线程正在运行并导致SIGABRT,实际上它确实如此,但是有连接似乎阻止了方法返回。
join
等待线程完成执行,所以当您加入时,startLogRotation
在此之前不会返回。
同样,正常的作用域和生命周期规则也适用于线程对象——当startLogRotation
返回时,logRotationThread
将被销毁。
如果线程在销毁时是"可连接的",则会出现错误。
最简单的解决方案可能是在InitialiseLibrary
中有LogRotation
成员,在LogRotation
中有thread
成员。
你可以在LogRotation
的析构函数中join
这个线程
主线程阻塞在这一行,等待logRotationThread结束。
logRotationThread.join();
你的主线程应该去做任何工作,它需要做的产卵后,其他线程,然后只有当它没有什么要做的应该join()
日志旋转线程。
"线程有一个奇怪的问题" -欢迎来到线程的世界!
我认为你误解了你创建的线程的堆栈,以及它将如何与主线程交互。创建的线程的堆栈从您告诉它开始的函数开始-当该函数完成时,线程死亡(这将允许join()停止阻塞)
关于线程之间的通信,我认为你应该读一下互斥锁,条件和信号量
据我所知,
logRotationThread是一个长时间运行的线程(在应用程序的整个持续时间内运行)。主线程不需要在logRotationThread上等待(连接)。
首先删除logRotationThread.join()
- 方法重写线程C++中的概念
- 使用基类中的派生方法运行线程,而无需使用模板
- 将线程中的数据存储到全局容器的最佳方法?
- 处理影响跨不同线程共享对象的定时回调的最佳方法是什么?
- 如何将带有参数的方法传递给线程以执行?
- C++ POCO - 如何在不使用 run() 方法的情况下启动线程池上的线程?
- 在销毁期间从另一个线程调用对象上调用方法是否未定义行为?
- C++中的多线程:连接线程的正确方法
- 使用包含互斥锁的类的方法实例化 cpp11 线程
- 如何在JNI中从线程内部调用JAVA方法
- 如何从另一个线程调用颤振引擎方法
- 在另一个线程上发出 QObject 信号的正确方法?
- 在C++线程内实现多个计时器的最安全方法
- C++ std::线程调用方法,从对象原因到调用此类的析构函数
- 将指针传递到另一个线程的正确方法
- 在另一个 QThread 上运行成员方法时,无法将事件发送到其他线程拥有的对象
- 支持多线程方法来构建数组中所有元素的集合吗
- 这两种线程方法之间有什么区别
- 什么是Qt中低延迟音频合成的最佳多线程方法
- 将不同的线程方法组合到Windows窗体应用程序中