C++ Microsoft SAPI:异步使用事件和泵消息进行对话

C++ Microsoft SAPI: Speak with event and Pump Message asynchronously

本文关键字:消息 对话 事件 SAPI Microsoft 异步 C++      更新时间:2023-10-16

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

C++ MSAPI 5:SetNotifyCallbackFunction 不起作用

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

现在我的问题是我需要异步完成消息泵。我已经尝试了std::thread,pthread和boost库。但是每当我将消息泵放入另一个线程时。泵出现故障。每当我尝试在另一个线程中调用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;
}

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

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

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

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

我昨天忘了回答我自己的问题。但我会把功劳归功于埃里克·布罗

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

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

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