线程问题,其中一个线程工作,但导致调用方法不返回

Threading issue where 1 thread works but causes the calling method to not return

本文关键字:线程 方法 返回 工作 调用 问题 一个      更新时间:2023-10-16

我目前正在学习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()