C 中的异步线
Asynchronous threads in C++
我们使用Visual Studio 2005来开发游戏(我们的某些计算机仍运行Windows 2000,这是将运行的最新版本,我们无法轻松地将其转换为较新版本无论如何(在C 中。
我们的音乐作曲家已经写了一些简短的曲目来测试系统,但是出现了一个问题:游戏在播放音乐或声音效果时冻结。
虽然这对SFX来说并不是一个特别的问题,但音乐是一个非常大的问题,因为我们需要在后台运行。
我认为我们可能可以在背景中创建第二个线程或进程以在循环中播放指定的曲目,但是当我搜索时,我找不到任何可用于此功能的东西,因为需要一个数据传输(尽管单向(在两个过程之间。
我看到的方式,我们应该能够从包含要播放的曲目编号的主程序中将命令传递到音乐过程 - 这应该很简单,但是我们最近已移动到C ,而不是目前对此非常有经验。
感谢您的任何建议。
P.S。请不要对我们使用过时的软件发表评论,我们这样做是为了娱乐而不打算将任何钱投入其中。
编辑:为了清楚起见,如果不清楚我们都在运行Windows,并且不打算将其移植到任何其他平台 - 我们正在运行Visual Studio 2005,但是计划是开始转到Visual Studio2008年或2010年,一旦我们可以获取适当的光盘和软件。
音乐除了哔哔声((;命令内置在标准Windows头文件(Windows.h(中。
我们想运行与主程序平行的次要过程,以允许背景音乐。
事实证明,两个过程之间的数据传输太大了,我们是否能够将启动变量作为轨道编号传递到打开时,并在完成后简单地杀死它?
在Visual Studio的情况下,声明为挥发性的变量将包括内存围栏操作(除非关闭此选项,否则默认情况下它是打开的(,从而可以在线程之间使用它们。鉴于此,该代码可以使用挥发性变量,以播放音乐曲目。我在下面包括了示例C代码。
我认为,在播放音乐时,蜂鸣声((不会受到CPU的限制(似乎不适合Windows XP(。
为了更准确的计时,可以使用TimeBeginperiod((将股票频率从64Hz(15.625 ms(提高到1000Hz(1 ms(。对于Windows XP和Windows 2000,TimeBeginperiod(1(会导致Ticker实际运行在1024Hz,而Sleep((和我的Guess Beep((和我的Guess Beep((通过每128个tick添加3个额外的tick tick,以效仿1000Hz ticker。在125毫秒的边界上。这意味着睡眠(1(可能偶尔需要近2毫秒(在42、84和125呼叫上(。
注意 - 最终,由于缺乏与之通信的硬件,Windows Vista和Windows XP 64位版本中对哔哔声的支持被删除。在Windows 7中,哔哔声被重写以将哔哔声传递给会话的默认声音设备。通常,这是声卡,除非在终端服务下运行,在这种情况下,蜂鸣声是在客户端上呈现的。
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679277(v = vs.85(.aspx
示例多线程"蜂鸣"代码。该代码使用PC扬声器在Windows XP上的预期工作。在Windows 7上,它使用声卡,笔记之间有一些沉默。
/*----------------------------------------------------------------------*/
/* mtbeep.c multi-thread beep demo */
/*----------------------------------------------------------------------*/
#include <windows.h>
/* include winmm.lib for timeBeginPeriod */
#pragma comment(lib, "winmm.lib")
#define TRACK0 0
#define TRACK1 1
#define TRACK2 2
#define TRACKX 3 /* exit thread 1 if trackx */
typedef struct {
DWORD dwFreq;
DWORD dwDuration;
}NOTE;
/*----------------------------------------------------------------------*/
/* data */
/*----------------------------------------------------------------------*/
static HANDLE htT1; /* thread 1 handle */
static DWORD dwThreadT1; /* thread id's (not used) */
static volatile DWORD dwTrack; /* beep track to play */
/* songs */
static NOTE anTrack0[4] = {300, 500, 450, 500, 600, 500, 0, 0};
static NOTE anTrack1[4] = { 0, 250};
static NOTE anTrack2[4] = {400, 500, 300, 500, 200, 500, 0, 0};
static NOTE anTrackx[4] = {0, 0};
/*----------------------------------------------------------------------*/
/* code */
/*----------------------------------------------------------------------*/
static DWORD WINAPI Thread0(LPVOID);
static DWORD WINAPI Thread1(LPVOID);
/*----------------------------------------------------------------------*/
/* main */
/*----------------------------------------------------------------------*/
DWORD main(DWORD argc, BYTE **argv)
{
timeBeginPeriod(1); /* set period to 1ms */
Sleep(128); /* wait for it to stabilize */
/* create thread */
htT1 = CreateThread(NULL, 0, Thread1, 0, 0, &dwThreadT1);
if(!htT1){
/* createthread failed */
goto exit0;}
Thread0((LPVOID)NULL); /* start Thread 0 */
exit0:
if(htT1){ /* close thread */
dwTrack = TRACKX;
WaitForSingleObject(htT1, INFINITE);
CloseHandle(htT1);}
timeEndPeriod(1); /* restore period */
return(0);
}
/*----------------------------------------------------------------------*/
/* Thread0 */
/*----------------------------------------------------------------------*/
static DWORD WINAPI Thread0(LPVOID lpvoid)
{
int i;
for(i = 0; i < 4; i++){
dwTrack = i%3;
Sleep(5000);
}
return 0;
}
/*----------------------------------------------------------------------*/
/* Thread1 beep thread */
/*----------------------------------------------------------------------*/
static DWORD WINAPI Thread1(LPVOID lpvoid)
{
NOTE *apTrack[4] = {anTrack0, anTrack1, anTrack2, anTrackx};
NOTE *pTrack = anTrack0; /* ptr to array of notes */
DWORD cTrack = TRACKX; /* current track */
int iNote = 0; /* note index */
while(dwTrack != TRACKX){ /* play a note loop */
if(cTrack != dwTrack){ /* if song changed */
iNote = 0; /* start at first note */
cTrack = dwTrack; /* of next song */
pTrack = apTrack[cTrack];
}
if(!pTrack[iNote].dwDuration) /* if end of song */
iNote = 0; /* reset note index */
if(pTrack[iNote].dwFreq) /* if note play it */
Beep(pTrack[iNote].dwFreq, pTrack[iNote].dwDuration);
else /* else silence */
Sleep(pTrack[iNote].dwDuration);
iNote++;
}
return(0);
}
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在C++中实现带有packaged_task的异步等待循环?
- 创建 Spdlog 异步文件记录器时遇到困难
- C ++异步键盘输入(标准方式)
- 在 gtkmm 中异步加载图像
- 带有 Boost.Beast 的异步读取标头
- 如何在 c++ 中异步调用静态方法?
- libcurl :C++处理多个异步请求
- 如何在C++上启动异步线程
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 增强 ASIO 和串行端口异步读取
- 使用 Qt5 SQL 进行异步数据库访问的策略
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- C++中真正的异步文件 IO
- 提升::Asio 异步聊天客户端停止与服务器通信
- 在 c++ 托管和异步运行中调用 c# 可执行文件
- std::异步与非静态成员函数
- 我有一个关于C++提升的问题:: asio 和 std :: 异步
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- std::异步导致死锁?