在 Microsoft Windows 中进行线程编程的经验

主要观点:帮助同事在基于 GUI 的 Windows 应用中添加工作线程,分享线程编程的经验。
关键信息:

  • 性能方面:将计算密集型工作转移到工作线程可让主线程更好地服务 GUI 请求。
  • 线程库:Windows 有多种线程库,同一应用中使用不同线程库可能导致危险的静默错误。
  • 内存栅栏:不同线程可在不同处理器核心,需特殊措施保证变量更新对其他线程可见,如使用::PostMessage等。
  • GUI 访问:应仅从主线程进行,工作线程可通过::PostMessage让主线程执行 GUI 操作,否则可能导致死锁。
  • 线程启动:AfxBeginThread默认会在不需要时删除线程句柄,若要自己管理可进行相应设置。
  • 共享库使用:如 DAO 数据库库,在不同线程中分配和释放可能导致崩溃。
  • 初始化:主线程和工作线程在初始化时应调用CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)AfxDaoInit(),完成时调用CoUninitialize()AfxDaoTerm()
  • 线程状态监测:可使用WaitForSingleObject监测线程状态,非阻塞或阻塞等待线程完成。
  • 竞态条件:是风险,可通过仔细推理避免,有工具可尝试查找但未使用。
    重要细节:
  • 不同编译器家族的线程库(如 GOMP 与 LOMP)有不同的线程运行时,混合使用可能出错。
  • 线程启动时隐式执行内存栅栏,保证新线程能正确看到所有内存位置的状态。
  • 未在网上找到涵盖所有这些问题的 MFC 线程模型的严格规范。
阅读 16
0 条评论