Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
线程池中大量磁盘访问期间(无响应)消息 我是一个爱好C++编程和多线程编程的程序员,开始我的第一个线程池尝试。 . 我已经到了校长们正在工作的地步_C++_Multithreading_User Interface_Wxwidgets - Fatal编程技术网

线程池中大量磁盘访问期间(无响应)消息 我是一个爱好C++编程和多线程编程的程序员,开始我的第一个线程池尝试。 . 我已经到了校长们正在工作的地步

线程池中大量磁盘访问期间(无响应)消息 我是一个爱好C++编程和多线程编程的程序员,开始我的第一个线程池尝试。 . 我已经到了校长们正在工作的地步,c++,multithreading,user-interface,wxwidgets,C++,Multithreading,User Interface,Wxwidgets,我试图实现的是从一个音乐文件(FLAC)中提取20个标签。一个会话中可能要扫描7000个文件 每个提取都是在具有16个线程的线程池中执行的单独活动, 最终结果(一个未来)被推送到一个结构向量上,供以后处理 线程池代码借用自: 我在Windows10Pro计算机上使用Code::Blocks 20.3、wxWidgets 3.1.3和MinGW 17.1 我现在面临的问题是,高级别的磁盘访问阻止了应用程序刷新窗口界面。 该窗口显示臭名昭著的(未响应)消息 我的应用程序由一个主框架类和一个面板类组

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

每个提取都是在具有16个线程的线程池中执行的单独活动, 最终结果(一个未来)被推送到一个结构向量上,供以后处理

线程池代码借用自:

我在Windows10Pro计算机上使用Code::Blocks 20.3、wxWidgets 3.1.3和MinGW 17.1

我现在面临的问题是,高级别的磁盘访问阻止了应用程序刷新窗口界面。 该窗口显示臭名昭著的(未响应)消息

我的应用程序由一个主框架类和一个面板类组成。被调用的函数是“自由函数”。 用于尝试和“强制”更新窗口的代码是:Refresh()和update()

采取的行动:

每200毫秒触发一次事件的WX定时器

一个单独的线程,带有一个while循环,睡眠时间为200ms,当线程处理结束时,可以使用原子bool停止

最后但并非最不重要,但仍然不有效

wxStopWatch swt;
for (auto &Fut : Futures)
{
    TagsStruct TLf = TagsStruct();
    TLf = Fut.get();
    vTrackTags.push_back(TLf);
    if (swt.Time() > 200)
    {
        // ToDo: code for updating one progress bar
        m_wnd->Refresh(); // m_wnd is a pointer passed from the Panel Class
        m_wnd->Update();
        swt.Start();
    }
}
秒表计时不一致(从平均200ms到370ms不等),但足以更新进度条

必须有一种机制来为窗口更新腾出时间。 我买了一个可以转换文件的应用程序。 它有时需要15分钟的时间来表演,而且它可以让16个进度条保持活动和踢腿。 因此,原则上,应该可以在线程运行时更新进度条

希望有人能帮我解决这个问题

路德

添加了按钮事件中的代码:

void FetchTags::m_btn_Fetch_OnButtonClick( wxCommandEvent& event )
{
    // Set Collection Name
    wxString wsCollection{m_textCtrl1->GetLineText(0)}, wsCol{"Empty"};
    if (wsCollection != "") { wsCol = wsCollection; };

    // Set number of threads
    int t_cnt = m_spinCtrl1->GetValue();
    if (wsTrackFiles.size() > 0)
    {
        Elements(false);
        auto TrackTags = ExtractMultiTags(t_cnt, wsTrackFiles, wsCol, this); // though thread-pool
        Elements(true);
        if (TrackTags.size() > 0)
        {
            // Grid is cleared in OnDropFiles()
            m_grid1->AppendRows(TrackTags.size());
            FillGrid(TrackTags);
            WriteToCSV(TrackTags);
        }
        std::cout << "i_cnt = " << i_cnt << std::endl;
    }
}
void FetchTags::m_btn_Fetch_onbutton单击(wxCommandEvent&event)
{
//设置集合名称
wxString wsCollection{m_textcrl1->GetLineText(0)},wsCol{“Empty”};
if(wsCollection!=“”){wsCol=wsCollection;};
//设置线程数
int t_cnt=m_spinCtrl1->GetValue();
如果(wsTrackFiles.size()>0)
{
元素(假);
auto TrackTags=ExtractMultiTags(t_cnt,wsTrackFiles,wsCol,this);//通过线程池
元素(真);
如果(TrackTags.size()>0)
{
//已在OnDropFiles()中清除网格
m_grid1->AppendRows(TrackTags.size());
填充网格(轨迹标记);
WriteToCSV(TrackTags);
}
std::cout Update();
swt.Start();
}
}
//卸载.dll
FreeTagsLibrary();
返回标签;
}
---从曲目文件中提取---

静态标记struct ExtractTrackTags(标记struct标记行、wxString wsFile、wxString wsCollection)
{
//将std::string转换为LPWSTR
LPWSTR wsFileName{ConvertString(wsFile)};
//加载标签
标记库加载(标记,wsFileName,ttAutomatic,TRUE);
如果(已加载标签库(标签,t自动))
{
/*提取音频属性*/
taudios;
if(!TagsLibrary_GetAudioAttributes(标记、TAudioType::atAutomatic和Attribs))
{ 
TagLine.PlayTime=std::_cxx11::to_字符串(Attribs.PlayTime);
//等等。。。
}
/*提取命名标记*/
//唱片艺术家
std::wstring ws05(TagsLibrary_GetTag(Tags,ConvertString(“相册艺术家”),ttAutomatic));

TagLine.AlbumArtist假设您的未来总是得到解决,您可以在刷新UI直到其准备就绪的同时,在每个未来上旋转一小段时间:

for (auto &Fut : Futures)
{
    while (true) {
        auto status = Fut.wait_for(100ms);
        if (status == std::future_status::ready) break;
        m_wnd->Refresh(); // Assuming these functions actually run the event loop
        m_wnd->Update();
    }
    TagsStruct TLf = Fut.get();
    vTrackTags.push_back(TLf);
}

或者,您可以保留阻塞循环,但在另一个线程中执行,并在准备就绪时将WxEvent发送回UI线程,例如在中。

听起来这可能是一个I/O受限的操作,在这种情况下,更多的线程只会使进程变慢,特别是在“旋转生锈”的硬盘驱动器上(与SSD相反)。你用1个线程试过了吗?如果没有别的,它会使“无响应”问题更容易找到。@Thomas。我用1个线程试过,结果是一样的。用16个线程,它完成处理的时间比1个线程少一半多一点。你在主(UI)上做了大量IO吗线程?不要。保持UI线程空闲并从工作线程更新它。@Botje。主UI线程仅用于与UI相关的命令和事件。按钮事件启动空闲函数以激活线程池和标记提取。您确定没有无意中阻塞UI线程吗?拥有线程池并正确使用线程池We’通常是两种不同的东西,差异可能是微妙而微妙的。我已经测试了您的第一个建议。Fut.Get()仍然会阻塞UI。我将查看您的第二个建议。您是否使用调试器验证它是否卡在Get调用中?窗口显示(未响应)执行7到10秒后返回消息。调试器有何帮助?执行速度将足够慢,以允许窗口更新。对吗?最终结果总是100%正常。当Windows确定您的程序“没有响应”时,调试器将告诉您堆栈顶部有什么函数。我假设更新()调用运行事件循环并处理消息,所以要么该假设为false,要么您在某处有另一个阻塞调用。
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;
}
#0 ??   ExtractMultiTags (th_cnt=th_cnt@entry=16, vwsFiles=..., wsCol=..., m_wnd=m_wnd@entry=0x1676f30) (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:167)
#1 0x402e12 FetchTags::m_btn_Fetch_OnButtonClick(this=0x1676f30, event=...) (f:/sdks/mingw-17.1/include/c++/9.2.0/bits/basic_string.h:263)
#2 0x417d68 wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const() (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#3 0x507c91 wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#4 0x508137 wxEvtHandler::SearchDynamicEventTable(wxEvent&) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#5 0x5084a5 wxEvtHandler::TryHereOnly(wxEvent&) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#6 0x50853b wxEvtHandler::ProcessEventLocally(wxEvent&) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#7 0x508622 wxEvtHandler::ProcessEvent(wxEvent&) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#8 0x50a71c wxEvtHandler::SafelyProcessEvent(wxEvent&) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#9 0x57c373 wxButton::SendClickEvent() () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#10 0x56095f    wxWindow::HandleCommand(unsigned short, unsigned short, HWND__*) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#11 0x56bcaf    wxWindow::MSWHandleMessage(long long*, unsigned int, unsigned long long, long long) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#12 0x55988f    wxWindow::MSWWindowProc(unsigned int, unsigned long long, long long) () (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:190)
#13 0x7ffeebf05c7d  ?? () (??:??)


#0 ??   std::unique_lock<std::mutex>::unique_lock (__m=..., this=0x162dc80) (f:/sdks/mingw-17.1/include/c++/9.2.0/bits/move.h:47)
#1 ??   Thread_Pool::execute<TagsStruct (*)(TagsStruct, wxString, wxString), TagsStruct&, wxString&, wxString&> (this=this@entry=0x162e6e0, function=function@entry=0x411612 <ExtractTrackTags(TagsStruct, wxString, wxString)>, args#0=..., args#1=..., args#2=...) (F:/Data/__C++/wxApps/Mtags/Threadpool.h:62)
#2 0x416ddb ExtractMultiTags(th_cnt=th_cnt@entry=16, vwsFiles=..., wsCol=..., m_wnd=m_wnd@entry=0x1676f30) (F:\Data\__C++\wxApps\Mtags\TrackTags.cpp:167)
#3 0x402e12 FetchTags::m_btn_Fetch_OnButtonClick(this=0x1676f30, event=...) (f:/sdks/mingw-17.1/include/c++/9.2.0/bits/basic_string.h:263)
for (auto &Fut : Futures)
{
    while (true) {
        auto status = Fut.wait_for(100ms);
        if (status == std::future_status::ready) break;
        m_wnd->Refresh(); // Assuming these functions actually run the event loop
        m_wnd->Update();
    }
    TagsStruct TLf = Fut.get();
    vTrackTags.push_back(TLf);
}