线程池中大量磁盘访问期间出现无响应消息

如何解决线程池中大量磁盘访问期间出现无响应消息

我是一名爱好程序员,学习C ++和多线程,并开始我的第一次线程池尝试。 。 我到了校长正在工作的地步。

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

每次提取是在具有16个线程的线程池中执行的单独活动, 并将最终结果(未来)推入结构的向量中以供以后处理。

线程池代码是借来的:

https://codereview.stackexchange.com/questions/221626/c17-thread-pool

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

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

我的应用程序包含一个主Frame类和一个Panel类。被调用的函数是“自由函数”。 尝试“强制”更新窗口的代码是:Refresh()和Update()。

已采取的措施:

每200毫秒触发一次事件的wxTimer。

一个带有while循环的单独线程,该线程休眠200ms,并且在线程处理结束时可以通过原子布尔停止。

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

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();
    }
}

秒表计时不一致(从平均200毫秒到370毫秒不等),但足以更新进度条。

必须有一种机制来腾出时间来更新窗口。 我购买了一个可转换文件的应用程序。 有时需要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;
    }
}

//-

std::vector<TagsStruct> ExtractMultiTags(int th_cnt,std::vector<wxString> vwsFiles,wxString wsCol,wxWindow *m_wnd)
{
wxStopWatch swf;
    // Load the TagsLibrary DLL
    if (!InitTagsLibrary())
    {
        //* Could not load the .dll
        wxString msg = "\tError while loading TagsLib.dll\n";
        wxMessageBox(msg,_("ERROR..."));
    }
    // Clear existing Vector of Futures
    vTrackTags.clear();
    // Create Thread Pool
    Thread_Pool Pool(th_cnt);
    std::vector<std::future<TagsStruct>> Futures;
    // Do the work
    for(auto &aTrack : vwsFiles)
    {
        TagsStruct TLp = TagsStruct();
        Futures.push_back(Pool.execute(ExtractTrackTags,TLp,aTrack,wsCol));
    }
    // Get the results
    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->Update();
            swt.Start();
        }
    }
    // Unload the .dll
    FreeTagsLibrary();
    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;
}

下面是带有断点的调用堆栈

“ Futures.push_back(Pool.execute(ExtractTrackTags,TLp,aTrack,wsCol));”

#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,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)>,args#0=...,args#1=...,args#2=...) (F:/Data/__C++/wxApps/Mtags/Threadpool.h:62)
#2 0x416ddb ExtractMultiTags(th_cnt=th_cnt@entry=16,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)

解决方法

假设您的期货总能得到解决,那么您可以在刷新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线程,例如在WxThreadHelper中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-