2

为了更好地理解这个问题,请参考我之前的问题:

C++ MSAPI 5:SetNotifyCallbackFunction 不起作用

在 Microsoft SAPI 中,为了在您使用时传递文本转语音事件,SetNotifyCallbackFunction您需要创建一个消息泵,下面是代码。

现在我的问题是我需要异步完成消息泵。我已经尝试过std::threadpthreadboost库。但是每当我将消息泵放在另一个线程中时。泵发生故障。Speak每当我尝试在另一个线程中调用时也是如此。我该如何解决这个问题?同样,我的目标是让 MSAPI与事件异步说话。

调用消息泵:

HANDLE hWait = pV->SpeakCompleteEvent();
WaitAndPumpMessagesWithTimeout(hWait, INFINITE);

实际的消息泵代码:

HRESULT WaitAndPumpMessagesWithTimeout(HANDLE hWaitHandle, DWORD dwMilliseconds)
{
    HRESULT hr = S_OK;
    BOOL fContinue = TRUE;

    while (fContinue)
    {
        DWORD dwWaitId = ::MsgWaitForMultipleObjectsEx(1, &hWaitHandle, dwMilliseconds, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
        switch (dwWaitId)
        {
        case WAIT_OBJECT_0:
            {
                fContinue = FALSE;
            }
            break;

        case WAIT_OBJECT_0 + 1:
            {
                MSG Msg;
                while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
                {
                    ::TranslateMessage(&Msg);
                    ::DispatchMessage(&Msg);
                }
            }
            break;

        case WAIT_TIMEOUT:
            {
                hr = S_FALSE;
                fContinue = FALSE;
            }
            break;

        default:// Unexpected error
            {
                fContinue = FALSE;
                hr = E_FAIL;
            }
            break;
        }
    }
    return hr;
}
4

2 回答 2

3

我怀疑您需要在调用 WaitAndPumpMessagesWithTimeout 之前创建消息队列。

有几种方法可以做到这一点:

  1. 称呼::PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE)
  2. 创建一个窗口(仅消息窗口在这里很有用)

当您Speak()在单独的线程上调用时,您也应该在该线程上创建 SAPI 对象。

于 2013-09-18T16:12:46.843 回答
1

我昨天忘记回答我自己的问题了。但我要感谢 Eric Brow

首先,我做异步事件的目的是将它用作其他语言的库。

我昨天研究的就像 Eric 所说的,所有的 SAPI 交互都必须发生在同一个线程上。因此,我通过创建一个派生自 CWinThread 的类来解决这个问题,该类也具有 SAPI 功能。然后我让包装函数与派生的 CWinThread 类交互。

来源: http: //www.codeproject.com/Articles/551/Using-User-Interface-Threads

于 2013-09-19T05:53:22.860 回答