3

waveOutAPIのスレッドセーフに関する情報が見つかりません。

新しいwaveOutハンドルを作成した後、次のスレッドがあります。

スレッド1:バッファ処理。これらのAPI関数を使用します。

  • waveOutPrepareHeader
  • waveOutWrite
  • waveOutUnprepareHeader

スレッド2:Gui、コントローラースレッド。これらのAPI関数を使用します。

  • waveOutPause
  • waveOutRestart
  • waveOutReset
  • waveOutBreakLoop

これらの2つのスレッドは、同じwaveOutハンドルを同時に使用しながら実行されています。私のテストでは、機能に問題は見られませんでしたが、それが安全であるという意味ではありません。

このアーキテクチャはスレッドセーフですか?waveOut APIのスレッドセーフに関するドキュメントはありますか?waveOut APIのスレッドセーフに関するその他の提案はありますか?

ありがとう。

4

4 に答える 4

4

一般に、waveOutAPIはスレッドセーフである必要があります。通常、waveOutOpen()は独自のスレッドを作成し、すべてのwaveOut*関数はそのスレッドにメッセージを送信するためです。しかし、私はあなたに証拠を与えることはできません...

ただし、どのような場合でも安全になるようにアプリケーションを変更できます。

  1. バッファ管理のためにスレッドを開始します。dwBufferThreadIdを覚えておいてください。
  2. GUIスレッドから、dwCallbackをdwBufferThreadIdに設定し、fdwOpenをCALLBACK_THREADに設定してwaveOutOpenを呼び出します。
  3. バッファ管理スレッド:事前にいくつかのバッファを「waveOutWrite」、GetMessage()のループ
  4. waveOutOpenは、バッファーが終了して新しいバッファーが必要になるたびにWOM_DONEを送信します。これは、そのスレッド内から新しいバッファーをwaveOutWriteする瞬間です。
  5. GUIスレッドからwaveOutPause、waveOutRestartなどを呼び出します(MSDNにはこれに反対するものはなく、バッファが別のスレッドからいっぱいになる場合でも、すべての例でこれが行われます)。

例1

100%確実にしたい場合は、Windowsメッセージ(WM_USER + 0)を取得して呼び出しPostThreadMessage( WM_USER+0, dwBufferThreadId, MY_CTL_PAUSE,0 )、バッファリングスレッドでそのメッセージを受信したら、waveOutPause()そこで呼び出します。Windowsのメッセージキューを使用すると、独自のメッセージキューを作成する手間が省けます;-)

于 2009-12-14T19:51:00.870 に答える
2

ドキュメントも表示されませんでしたが、waveOutWriteの呼び出しが、同じハンドルでのWaveOutRestartの呼び出しと同時に実行しても安全であるとは考えられません。

VS2010 Beta2を使用している場合は、エージェントライブラリのさまざまなウォークスルーを調べて、書き込み、一時停止、再起動などのメッセージを渡すプロデューサーコンシューマーの問題に変えようとします。

Visual Studio 2010を使用していない(または使用できない)場合は、スレッドと、処理するコマンドを格納する内部同期キューを使用して、これをプロデューサーコンシューマーの問題に分解する方法を見つけることをお勧めします。メッセージがそれほど頻繁ではなく、このキューで動作しているスレッドが2つしかない場合は、std ::queue...の周りに単純な古いWin32クリティカルセクションを配置することで回避できる可能性があります。

お役に立てれば。

于 2009-12-10T06:30:17.410 に答える
2

残念ながら、シングルスレッド環境でも安全ではありません。議論のためにこの質問を見てください:

waveOutWrite()がデバッグヒープで例外を引き起こすのはなぜですか?

これをMicrosoftに報告しようとすると、バグが閉じられました。彼らはそれを修正するつもりはありません。

于 2009-12-18T12:15:11.463 に答える
1

スレッドセーフかもしれませんが、スレッドセーフであると述べている公式ドキュメントが見つからない場合は、そうではないと想定して、独自のスレッド同期を追加してください。軽量のEnterCriticalSection/LeaveCriticalSectionの実装は、おそらく12行以下のコードです。

APIがスレッドセーフであることを保証するテストはありません。問題は、一部のCPUまたはバス速度または一部のサウンドカードを備えた一部のアーキテクチャでのみ発生する可能性があります。あなた(またはMicrosoft)のどちらも、考えられるすべての構成をテストすることはできません。

また、MicrosoftやIntel、サウンドカードの製造元やドライバーの作成者が将来の実装で何をするかについても想定しないでください。

于 2009-12-16T01:28:41.180 に答える