C 中的异步线

Asynchronous threads in C++

本文关键字:异步      更新时间:2023-10-16

我们使用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);
}