如何使用PostThreadMessage使用shared_ptr?

 郭原雪2865 发布于 2022-12-23 14:36

我想std::shared_ptr在调用其他窗口或线程时升级我的MFC生产代码以使用智能指针.这样的呼叫是SendMessage,PostMessage并且PostThreadMessage通过wparamlparam分别是unsigned intlong.目前,我创建了一个类对象,一个新的对象,使调用传递一个指向该对象的指针,使用接收端的对象然后删除它.

由于shared_ptr我的其余代码工作得很好,我想至少探讨为什么我不能对Windows调用做同样的事情.

目前的电话:

auto myParams = new MyParams(value1, value2, value3);
PostThreadMessage(MSG_ID, 0, reinterpret_cast< LPARAM >( myParams );

ReceivingMethod::OnMsgId( WPARAM wParam, LPARAM lParam)
{
  auto myParams = reinterpret_cast< MyParams * >( lParam );
  ... // use object
  delete myParams;
}

到类似C++ 11的智能指针调用:

std::shared_ptr< MyParams > myParams( new MyParams( value1, value2, value3 ) );
PostThreadMessage( MSG_ID, 0, ???myParams??? );

ReceivingMethod::OnMsgId( WPARAM wParam, LPARAM lParam )
{
  auto myParams = ???lParam???;
  ... // use object
}

编辑1:

@Remy Lebeau:以下是使用unique_ptr传递方法修改的示例代码,但是,在传递对象时,代码中存在泄漏:

struct Logger
{
  Logger()
  {
    errorLogger = ( ErrorLogger * )AfxBeginThread( RUNTIME_CLASS( ErrorLogger ), THREAD_PRIORITY_BELOW_NORMAL );
  }

  ~Logger()
  {
    // gets properly dtor'ed upon app exit
  }

  void MakeLogMsg( ... );

  ErrorLogger * errorLogger;
  std::unique_ptr< LogParams > logParams;
};

Logger logger;
std::recursive_mutex logParamsRecursiveMu; // because of multiple requests to lock from same thread

struct ErrorLogger : public CWinThread
{
  ErrorLogger()
  {
  }

  ~ErrorLogger()
  {
    // gets properly dtor'ed before logger upon app exit
  }

  afx_msg void OnLog( WPARAM wParam, LPARAM lParam );
};

void Logger::MakeLogMsg( ... )
{
  // construct msg from logparams 

  // make msg smart object using unique ptr and send to errorlogger thread queue
  logParams = std::make_unique< LogParams >();

  // set logparams

  // with the addition of the mutex guard, the leaks are gone
  logParamsRecursiveMu.lock();
  logger.errorLogger->PostThreadMessage( ONLOG_MSG, 0, reinterpret_cast< LPARAM >( logParams.get() ) );
  logParams.release(); // no longer owns object
  logParamsRecursiveMu.unlock();
}

void ErrorLogger::OnLog( WPARAM wParam, LPARAM lParam )
{
  std::unique_ptr< LogParams > logParams( reinterpret_cast< LogParams * >( lParam ) );
}

请注意,当我注释掉unique_ptr的传递时,泄漏消失了.我的代码与使用此方法的代码有何不同?

EDIT2:

关于@Remy Lebeau如何std::unique_ptr使用代替的答案std::shared_ptr,我在下面的评论中说,"......没有额外的对象可以实现.没有明显的缺点." 嗯,这不是真的.该MyParams对象具有用于每个不同类型的消息被创建.有些应用可能只有几种类型,但有些可能有100种或更多.每次我想在另一边执行一个函数时,我必须创建一个新结构,它有一个构造函数,它接受目标调用的所有参数.如果有很多,实施起来非常繁琐,难以维护.

我认为仅通过传递参数就可以消除结构构建阶段.

显然有新的C++ 1x结构可以帮助实现这一目标.其中一个可能std::forward_as_tuple就是"构造一个对args中参数的引用元组,这些参数适合作为函数的参数转发".

对于我的应用程序,我通过模板化解决了问题MyParams,但对于任何想要避免添加大量结构的人,他可能想要使用元组之类的东西.

编辑3:@ RemyLebeau的答案号1和@ rtischer8277的答案号5都是正确的.不幸的是,StackOverflow无法识别多个正确的答案.这个StackOverflow限制反映了一种有缺陷的心理语言学假设,即语言语境对于同一语言组是普遍的,而事实并非如此.(参见Roger Harris关于固定代码语言神话的"整合语言学概论",第34页).为了回应我原来的帖子,@ RemyLebeau根据显示newed 的发布代码所描述的上下文回答了这个问题MyParams(参见编辑2:更多解释).很久以后在答案5(rtischer8277)中,我根据问题的原始措辞回答了这个问题,该问题询问是否std::shared_ptr可以跨线程使用PostThreadMessage.作为一个合理的结果,我已经将正确答案重新分配给@RemyLebeau,这是第一个正确的答案.

编辑4:我在这篇文章中添加了第三个合法答案.见第6 回答开头@Remy勒博和@ rtischer8277迄今已提交了两个答案我原来的帖子....此解决方案的作用是将跨线程访问转换为概念上简单的RPC(远程过程调用).虽然本答案显示了如何使用a future来控制所有权和同步,但它没有说明如何创建具有任意数量参数的消息对象,这些参数可以安全地在PostThreadMessage调用的任一侧使用.该功能在StackOverflow上的解决答案发出传递参数包在使用forward_as_tuple遗留函数签名.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有