使用 c++11 中的新 std::async,我想我可能会尝试实现 OutputDebugString 的异步版本,以消除由于我通常通过通常的方式大量打印每个小细节而导致的一些性能下降输出调试字符串函数。

所以这是我原来的同步 OutputDebugString 实现(有效):

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

以下是我对异步版本(不起作用)的非常幼稚的尝试:
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 可能比尝试在函数本身内部启动异步作业更好(它有效,但很麻烦):
auto dstring = std::async([]{ OutputDebugStringN("[NovelScript::ParseTokens] searched bookmark: \"%s\" does not exist\n", bookmark.c_str());} );

所以我想问两个问题:
  • 我应该如何实现 OutputDebugString 的异步版本?
  • 我是否应该尝试实现 OutputDebugString 的异步版本?

  • 对上述代码的批评和任何其他评论也非常受欢迎。

    最佳答案

    我认为您应该为您的消息创建一个队列,而不是在每次调用您的函数时启动一个线程,这样您的消息将以正确的顺序输出干净。

    所以你的功能例如OutputDebugStringN(const char *format, ... ) 将创建消息字符串,然后将单独的打印输出线程读取的字符串排队。该线程将调用 OutputDebugString

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

    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");
    ...
    

    关于C++ 异步 OutputDebugString,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14536402/

    10-11 17:59