如何使用 PlaySound 同时执行其他功能?
Posted
技术标签:
【中文标题】如何使用 PlaySound 同时执行其他功能?【英文标题】:How can you perform other functions simultaneously with PlaySound? 【发布时间】:2019-06-13 11:05:39 【问题描述】:我正在编写一个 C++ Windows 应用程序,它需要从一个数组中播放一首随机选择的歌曲,并且用户需要能够通过单击一个按钮来播放列表中的另一首歌曲。你会如何停止第一首歌曲的声音以播放第二首歌曲?
通过按下播放第一首歌曲的按钮,播放音频资源,但是我的程序不再响应任何点击,并且代码在歌曲完成之前不会继续。我曾尝试使用 CreateThread(),但无济于事,因为我的程序仍处于无响应状态。
包含 PlaySound 的函数:
LPTHREAD_START_ROUTINE WINAPI PlayWavFile(int resource)
PlaySound(MAKEINTRESOURCE(resource), hInst, SND_RESOURCE | SND_SYNC);
return 0;
WndProc 函数中判断按钮按下结果的情况:
case WM_COMMAND:
if (LOWORD(wParam) == 1)
HANDLE hThread = CreateThread(
NULL,
0,
PlayWavFile(i),
NULL,
NULL,
NULL
);
else if (LOWORD(wParam) == 2)
HANDLE hPlaySecond = CreateThread(
NULL,
0,
PlayWavFile(j),
NULL,
NULL,
NULL
);
else if (LOWORD(wParam) == 3)
HANDLE hStop = CreateThread(
NULL,
0,
PlayWavFile(NULL),
NULL,
NULL,
NULL
);
break;
此外,如果我尝试单击应将 wParam 值设为 3 的按钮,则程序会遇到异常,该异常指出:
Audio Player.exe 在 0x00000000 处引发异常:0xC0000005:执行位置 0x00000000 的访问冲突。发生了。
最终目标是程序在后台播放音乐时做出响应。
【问题讨论】:
与基本问题无关,但绝对与您的解决方案尝试有关,您在创建每个线程时都会泄漏线程句柄。如果您不打算通过 waitforsingleobject 或类似方法等待线程,则应关闭从 CreateThread 返回的线程句柄。 【参考方案1】:只需使用SND_ASYNC
而不是SND_SYNC
直接调用PlaySound
。这将导致PlaySound
立即返回并在后台播放声音。
没有必要为此纠结线程。
【讨论】:
谢谢,这立即奏效了。不敢相信我没有想到这一点。【参考方案2】:当你这样做时
HANDLE hThread = CreateThread(
NULL,
0,
PlayWavFile(i),
NULL,
NULL,
NULL
);
您正在调用函数PlayWavFile
,并使用它返回的值作为要调用的线程函数。而且由于函数总是返回0
,它是一个空指针,它相当于
HANDLE hThread = CreateThread(
NULL,
0,
nullptr,
NULL,
NULL,
NULL
);
线程函数参数的类型为LPTHREAD_START_ROUTINE
,它是一个指向函数的指针,该函数接受LPVOID
参数并返回DWORD
。
你需要相应地改变你的线程函数,然后调用CreateThread
as
HANDLE hThread = CreateThread(
NULL,
0,
&PlayWavFile, // Pass a pointer to the function
reinterpret_cast<LPVOID>(i), // The argument to pass
NULL,
NULL
);
有了这个PlayWavFile
可能看起来像
DWORD PlayWavFile(LPVOID argument)
int resource = reinterpret_cast<int>(argument);
PlaySound(MAKEINTRESOURCE(resource), hInst, SND_RESOURCE | SND_SYNC);
return 0;
【讨论】:
我完全按照你说的做了,收到了这个错误:“DWORD (*)(LPVOID arg)”类型的参数与“LPTHREAD_START_ROUTINE”类型的参数不兼容 @SiggersLPTHREAD_START_ROUTINE
是线程过程的函数指针类型。它 not 是线程过程的正确返回值类型,因为您似乎正在使用它。您的函数应该 (a) 返回一个 DWORD
,(b) 使用 WINAPI
调用约定,以及 (c) 采用单个 LPVOID
参数。并注意我在您的问题下方的一般 cmets 中所说的泄漏线程句柄;这很重要。以上是关于如何使用 PlaySound 同时执行其他功能?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Python 中的 playsound 模块同时播放两种声音?