2015-05-14 109 views
0

更新:我发现他们发布的信号量不是监视器线程正在等待的信号量!我使用cout<<ready来查找线程正在释放的信号量是00000394,这不是监视器线程正在等待的信号量的句柄。这个问题的可能原因是什么?谢谢!为什么释放信号但WaitForSingleObject()仍然卡住?


我是Windows中的多线程编程的新手。今天,当我编写我的在线游戏服务器时,我尝试在Windows中使用信号量。它是基于IOCP编写的,因此每条消息都在单独的线程中处理。一场比赛由4名球员组成。

我期望它做的是:当收到一条消息时,一个新的线程启动并释放一个ready。有一个监视器线程正在等待4 ready,然后释放4 all_ready。每个线程等待一个all_ready并继续。

的代码是在这里:

CGameHost是一个4人游戏经理。

CGameHost::CGameHost(void) 
{ 
    init_times=0; 
    ready = CreateSemaphore(NULL, 0, 4, NULL); 
    read = CreateSemaphore(NULL, 0, 4, NULL); 
    all_ready = CreateSemaphore(NULL, 0, 4, NULL); 
    all_read = CreateSemaphore(NULL, 0, 4, NULL); 
    monitor_thread = (HANDLE)_beginthreadex(NULL, 0, Monitor, (LPVOID)this, NULL, 0); 
} 

unsigned __stdcall CGameHost::Monitor(LPVOID p) // a static function 
{ 
    CGameHost *nowp = (CGameHost *)p; 
    while(true) 
    { 
     int i; 
     for(i=1;i<=MAX_PLAYER;i++) 
     { 
      WaitForSingleObject(nowp->ready, INFINITE);//stuck here 
      cout<<"Get Ready!"<<endl; // This is not outputed, which means it stucks in the last row. 
     } 

     for(i=1;i<=MAX_PLAYER;i++) 
     { 
      ReleaseSemaphore(nowp->all_ready, 1, NULL); 
     } 

     for(i=1; i<=MAX_PLAYER; i++) 
     { 
      WaitForSingleObject(nowp->read, INFINITE); 
     } 

     for(i=1; i<=MAX_PLAYER;i++) 
     { 
      ReleaseSemaphore(nowp->all_read, 1, NULL); 
     } 
    } 
    return 0; 
} 

void CGameHost::ReleaseReady() 
{ 
    ReleaseSemaphore(ready, 1, NULL); 
} 

void CGameHost::WaitAllReady() 
{ 
    WaitForSingleObject(all_ready, INFINITE); 
} 

void CGameHost::ReleaseRead() 
{ 
    ReleaseSemaphore(read, 1, NULL); 
} 

void CGameHost::WaitAllRead() 
{ 
    WaitForSingleObject(all_read, INFINITE); 
} 

DataProcess::Game是传入游戏消息的消息处理程序。

CMessage Dataprocess::Game(CMessage* recv_msg) 
{ 
    CMessage ret; 
    int now_roomnum = recv_msg->para1; 
    int now_playernum = recv_msg->para2; 
    if(true) 
    { 
     cout<<"Received Game Message: "<<endl; 
     cout<<"type2 = "<<recv_msg->type2; 
     cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl; 
    } 

    if(recv_msg->type2 == MSG_GAME_OPERATION) 
    { 
     ret.type1 = MSG_GAME; 
     ret.type2 = MSG_GAME_OPERATION; 

     cout<<"Entered from "<<now_playernum<<endl; 

     game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg); 
     game_host[now_roomnum].ReleaseReady(); 

     cout<<"Released Ready from "<<now_playernum<<endl;//this is shown 

     game_host[now_roomnum].WaitAllReady();//stuck here 

     cout<<"AllReady from"<<now_playernum<<endl;//not shown 

    } 
    return ret; 
} 

您的回复对于像我这样的Windows多线程程序员的初学者会有很大的帮助!谢谢!

+0

你可能想要的是使用WaitForMultipleObjects –

+0

嗯...... IOCP并不意味着每条消息都在单独的线程上处理。也许你应该包括你的IOCP代码呢? – Luaan

+1

对我来说,就像你在锁定你的消息处理程序。第一位玩家准备就绪后,不能再处理任何消息。你必须重新考虑这一点。 –

回答

0

好吧,我解决我自己。原因是我在创建线程后再次使用了CreateSemaphore,使得播放器线程访问了与监视器线程不同的信号灯...对不起我的愚蠢,并且非常感谢您告诉我这么多!

2

如果我理解你的需求,你应该有这样的事情..

HANDLE hPlayersReady [4]; HANDLE hAllPlayed;

创建这5个事件,然后在你的监视线程, 做这样的事情......

while(true) 
{ 
// Wait for all players to move 
WaitForMultipleObjects(4, &hPlayersReady, true, INFINITE); 
// Process move 
... 
// Advise players the move was processed... 
SetEvent(hAllPlayed); 
} 

并在您的播放器线程X

while(true) 
{ 
// Make my move 
... 
// Advise monitor I'm ready 
SetEvent(hPlayersReady[X]); 
// Wait for ready to do another move 
WaitForSingleObject(hAllPlayed); 
} 
+0

谢谢你的回复,但我不认为它会起作用,因为'hAllPlayed'必须被采取4次,我想知道它是否只能被读取一次... – DarkZero

+0

看起来你会有来解释信号量和事件之间的区别。 –

+0

@DarkZero,我没有得到你的评论,你是什么意思,“必须采取4次”? –

相关问题