首页 > 解决方案 > 将结构返回到线程池的 C++ 传递函数会产生不稳定的结果并“挂起”

问题描述

我是一名爱好程序员,学习 C++ 和多线程。在我第一次尝试线程池时遇到了一些麻烦。感谢我在这个论坛收到的建议。我已经到了校长工作的地步。

我想要实现的是从音乐文件(FLAC)中提取 20 个标签。一个会话中可能需要扫描 7000 个文件。

每次提取都是一个单独的活动,最终结果(未来)被推送到结构向量以供以后处理。

我在 Windows 10 Pro 计算机上使用 Code::Blocks 20.3 和 MinGW 17.1。

该项目编译没有错误或警告。

只有 1 个线程,应用程序运行完美。

但是,当我在池中使用 2 个线程时,“ExtractTrackTags”函数会在要返回的结构中返回不稳定的值,并且应用程序通常会“挂起”。

我怀疑我正在传递的结构要么不够长,要么在线程池之间共享。我尝试使用空结构向量(在所有文件完成后清除),但这没有帮助。此外,当池中的线程数高于我提供的文件数时,应用程序“挂起”。

我希望有人可以帮助我完成这项工作。谢谢你。

路德。

---标题---

#ifndef TRACKTAGS_H_INCLUDED
#define TRACKTAGS_H_INCLUDED
//-
#include "Threadpool.h" // .h and .cpp from https://codereview.stackexchange.com/questions/221626/c17-thread-pool
#include <iostream>  // Required for comdef.h
#include <comdef.h>  // LPWSTR conversion
#include <filesystem>
#include <string>
#include <vector>
#include <sstream>  // For threadID
#include <thread>  // For threadID
#include <wx/string.h>
//-
struct TagsStruct
{
    bool OK;
    wxString ThreadID;  //  For testing purposes only
    wxString PlayTime;
    wxString AlbumArtist;
    wxString Collection;
    // etc...
};
//-
std::vector<TagsStruct> ExtractMultiTags(std::vector<wxString> vwsFiles, wxString wsCol);
//-
#endif // TRACKTAGS_H_INCLUDED

---通过线程池调用“ExtractTrackTags”的提取函数---

std::vector<TagsStruct> ExtractMultiTags(std::vector<wxString> vwsFiles, wxString wsCol)
{
    // Clear existing Vector of Futures
    vTrackTags.clear();
    // Get max threads
    unsigned int th_cnt{std::thread::hardware_concurrency()};
    th_cnt = 1; // For testing purposes only
    Thread_Pool Pool(th_cnt);
    std::vector<std::future<TagsStruct>> Futures;
    for(auto &aTrack : vwsFiles)
    {
        TagsStruct TSp = TagsStruct();
        Futures.push_back(Pool.execute(ExtractTrackTags, TSp, aTrack, wsCol));
    }
    for (auto &Fut : Futures)
    {
        TagsStruct TSf = TagsStruct();
        TSf = Fut.get();
        vTrackTags.push_back(TSf);
    }
    return vTrackTags;
}

---从曲目文件中提取---

static TagsStruct ExtractTrackTags(TagsStruct TagLine, wxString wsFile, wxString wsCollection)
{
    // Convert std::string to LPWSTR
    LPWSTR wsFileName{ConvertString(wsFile)};
    // Load the tags
    TagsLibrary_Load(Tags, wsFileName, ttAutomatic, TRUE);
    if (TagsLibrary_Loaded(Tags, ttAutomatic))
    {
        /* Extract the Audio Attributes */
        TAudioAttributes Attribs;
        if (!TagsLibrary_GetAudioAttributes(Tags, TAudioType::atAutomatic, &Attribs))
        { 
            TagLine.PlayTime = std::__cxx11::to_string(Attribs.PlayTime);
            // etc...
        }
        /* Extract the named TAGs*/
        //AlbumArtist
        std::wstring ws05(TagsLibrary_GetTag(Tags, ConvertString("ALBUMARTIST"), ttAutomatic));
        TagLine.AlbumArtist << std::string(ws05.begin(), ws05.end());
        // etc...
    }
    else
    {
        TagLine.OK = false;
        wxString msg = "\tNo tags found in:\n" + wsFile ;
        wxMessageBox(msg, _("ERROR..."));
    }

    return TagLine;
}

标签: c++multithreading

解决方案


HTags TagsinExtractTrackTags看起来可疑地像一个全局变量。如果情况确实如此,那么这就是您的问题的原因。将其范围缩小到ExtractTrackTags(因此每个线程都有自己的独立副本),问题应该自行解决。


推荐阅读