为什么在“QueueUserWorkItem”中使用“SND_SYNC”不好?

时间:2011-06-22 16:22:45

标签: c++ multithreading visual-c++ asynchronous

Larry Osterman writes关于微软代码中发现的真正错误,违规代码是

static DWORD WINAPI _PlayBeep(__in void* pv)
{
    UNREFERENCED_PARAMETER(pv);
    PlaySound(L".Default"NULL, SND_SYNC | SND_ALIAS);
    return 0;
}

LRESULT WndProc(...)
{
    :
    :
    case WM_KEYDOWN:
        if (!_AcceptInputKeys(wParam, lParam))
        {
            QueueUserWorkItem(_PlayBeep, NULL, 0);
        }
        break;
}
拉里问:

  

考虑到代码的简单性   以上,为了得到正确的答案,它是   还不足以说出什么是错的   代码(问题应该是   令人目眩的明显)。你还需要   能够解释为什么这么糟糕   (换句话说,什么打破了你   这样做。)

最好的答案是简短的评论是不够的,

  

大卫非常接近正在发生的事情   错了 - 现在想想的背景   申请。

有人可以完全解释这段代码运行时发生了什么吗?

1 个答案:

答案 0 :(得分:1)

阅读答案页面,它有一个非常详细的解释

http://blogs.msdn.com/b/larryosterman/archive/2009/06/29/what-s-wrong-with-this-code-part-26-the-answer.aspx

基本上,不要将QueueUserWorkItem用于长时间运行的工作项,因为这可能会导致进程中的线程耗尽,或者如果等待工作项完成就会以非常难以调试的方式死锁(必然)有限大小的线程池。同样适用于此API的.Net等效项ThreadPool.QueueUserWorkItem btw。

在这种特定情况下,工作项触发器(“按下向下键”)和结果线程工作项(“发出同步哔声”)非常不平衡,因此如果用户按住或反复按下他/她的向下键,这个过程很快就会遇到致命的问题。