首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++异步OutputDebugString

C++异步OutputDebugString
EN

Stack Overflow用户
提问于 2013-01-26 11:17:42
回答 2查看 1.7K关注 0票数 4

使用新的c++11中的std::异步,我想我可以尝试实现OutputDebugString的异步版本,以使我摆脱一些性能下降,这些性能下降是由于我通常通过通常的OutputDebugString函数对每一个细节进行重打印而造成的。

下面是我最初的同步OutputDebugString实现(它可以工作):

代码语言:javascript
复制
static void OutputDebugStringN(const char *format, ...)
{
    char outstring[256];
    memset(outstring, 0, sizeof(outstring));

    try
    {
        va_list args = {0};
        va_start(args, format); //args = (va_list) (&format+1);

        vsprintf_s(outstring, format, args);

        va_end(args);

        OutputDebugString(outstring);
    }
    catch (...) //most likely reference val arg error (va_list doesn't support ref args)
    {
        OutputDebugString("[OutputDebugStringN] Something went wrong\n");
    }
}

下面是我对异步版本的天真尝试(它不起作用):

代码语言:javascript
复制
static void OutputDebugStringN(const char *format, ...)
{
    auto future = std::async([]{
        char outstring[256];
        memset(outstring, 0, sizeof(outstring));
        try
        {
            va_list args = {0};
            va_start(args, format); //args = (va_list) (&format+1);

            vsprintf_s(outstring, format, args);

            va_end(args);

            OutputDebugString(outstring);
        }
        catch (...) //most likely reference val arg error (va_list doesn't support ref args)
        {
            OutputDebugString("[OutputDebugStringN] Something went wrong\n");
        }
    }); 
}

由于上述操作不起作用,我现在开始认为异步调用OutputDebugStringN可能比尝试在函数内部启动异步作业要好得多(这是可行的,但很麻烦):

代码语言:javascript
复制
auto dstring = std::async([]{ OutputDebugStringN("[NovelScript::ParseTokens] searched bookmark: \"%s\" does not exist\n", bookmark.c_str());} );

这里有两个问题我想问:

  1. 我应该如何实现OutputDebugString的异步版本?
  2. 我是否应该尝试实现OutputDebugString的异步版本?

对上述守则的批评和任何其他评论也是非常欢迎的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-26 11:29:43

我认为您应该为您的消息设置一个队列,而不是在每次调用函数时启动一个线程,这样您的消息就可以按照正确的顺序清晰地输出。

因此,您的函数(例如,OutputDebugStringN(const char *format, ... ) )将创建消息字符串,然后将独立打印出线程从中读取的字符串排队。这个线程会调用OutputDebugString

这里有一个例子--虽然不完整,但是没有错误处理和print_from_queue应该被修改来运行直到某些终止条件,并且对CPU更友好一些。

代码语言:javascript
复制
std::mutex g_m;
std::deque<std::string> que;
std::atomic<bool> endcond = false;

void queue(std::string msg)
{
  std::lock_guard<mutex> _(g_m);
  que.push_back(msg);
}

void print_from_queue()
{
  while ( !endcond )
  {
    if ( que.size() )
    {
      std::lock_guard<mutex> _(g_m);
      std::string msg = que.front();
      que.pop_front();
      OutputDebugStringA(msg.c_str());
    }
  }
}

int debugf( const char *format,... )
{
  std::vector<char> line(256);
  va_list args;
  va_start( args, format );
  int len = vsprintf_s( &line[0], line.size(), format, args );
  va_end( args );
  queue( &line[0] );
  return len;
}

int _tmain(int argc, _TCHAR* argv[])
{
  auto thr = std::async( std::launch::async, print_from_queue );
  debugf("message1");
  debugf("message2");
...
票数 9
EN

Stack Overflow用户

发布于 2013-01-26 11:40:46

对上述代码和C++异步函数的批评::p

std::异步的返回值是std::future类型的对象。std::期货的析构函数由std::异步创建,等待任务执行。所以当你这么做的时候

代码语言:javascript
复制
auto future = std::async(...

代码语言:javascript
复制
auto dstring = std::async([]{

它创建一个类型为std::OutputDebugStringN的对象,当您离开OutputDebugStringN的作用域时,它调用std::前途的析构函数,这个析构函数会阻塞直到任务被执行。

在我看来,这是C++的一个缺陷。这有点愚蠢(希望这不会冒犯任何人:p),它完全违背了异步的目的。为了得到大多数人期望的行为(显然,您是预期的),您必须保存一个std::未来对象的列表,然后花费精力(和处理时间)来确定销毁列表中单个std::未来对象的正确时间。这就是执行部分中问题1的答案。对于#2,我认为您不应该在每次调试消息的基础上为此目的使用std::异步。我认为它创造的问题比它解决的多。

我不知道有什么优雅的方法可以绕过这件事。也许其他人可以插话。

至于如何实现异步版本的OutputDebugString,我只需创建一个由字符串组成的生产者-消费者队列。已经有很多问题被问到了,你可以用谷歌( google )的生产者-消费者队列来了解细节。生产者是发出消息的主线程。使用者是一个线程(或多个线程),它从队列中提取元素并调用窗口的OutputDebugString。

编辑:如果我冒犯了任何异步爱好者,我想补充一下,std::异步对于并行计算非常有用,就像使用GPU一样。我怀疑它是为开发并行硬件而设计的。例如:

代码语言:javascript
复制
      // merge sort
      {
           auto left =  std::async(.....);  // merge_sort left
           auto right =  std::async(.....);  // merge_sort right
      }

      merge

这样,在我们合并之前,必须对左和右进行排序。如果没有,则等待直到它们都被排序,但是它允许同时处理左和右的机会。

如果你做过CUDA或任何you编码,这应该很熟悉.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14536402

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档