定时器与多线程 SetTimer and Multi-Thread 每个线程独立使用一个定时器

前几天,一个同学让我帮他做操作系统课程里的 生产者——消费者 模拟程序,需求如下:
  将生产者和消费者模拟算法封装在一个动态链接库中,主程序调用相关函数。生产者放入产品和消费者取走产品的速度可调节。
分别用循环队列和栈实现。

一般模拟这个算法都是生产这,消费者各开一个线程,同步访问一个共享缓冲区。但是需求要求能调节速度,我的思路是在
每个线程里单独创建一个定时器,但是Windows下定时器特性是:
   每隔定时时间,Windows系统放入一个 WM_TIMER 消息到应用程序的消息队列中。
所以我的解决方案如下:
  1. /* 更改定时器的消息 */
  2. #define WM_SETTIMER WM_USER + 100
  3. /* 生产者线程函数 */
  4. DWORD WINAPI ProducerFunc(LPVOID lpParameter)
  5. {
  6.     MSG msg;
  7.     UINT producerTimerId;
  8.     /* Create a message queue for this thread */
  9.     PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  10.     producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL);
  11.     while(GetMessage(&msg, NULL, 0, 0))
  12.     {
  13.         if(msg.message == WM_TIMER)
  14.         {
  15.             WaitForSingleObject(g_hEmptySemaphore, INFINITE);
  16.             WaitForSingleObject(g_hMutex, INFINITE);
  17.             Producer();
  18.             ReleaseMutex(g_hMutex);
  19.             ReleaseSemaphore(g_hFullSemaphore, 1, NULL);
  20.         }
  21.         else if(msg.message == WM_SETTIMER)
  22.         {
  23.             KillTimer(NULL, producerTimerId);
  24.             producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL);
  25.         }
  26.         else
  27.         {
  28.             TranslateMessage(&msg);
  29.             DispatchMessage(&msg);
  30.         }
  31.     }
  32.     KillTimer(NULL, producerTimerId);
  33.     return 0;
  34. }
  35. /* 消费者线程函数 */
  36. DWORD WINAPI ConsumerFunc(LPVOID lpParameter)
  37. {
  38.     MSG msg;
  39.     UINT consumerTimerId;
  40.     PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  41.     consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL);
  42.     while(GetMessage(&msg, NULL, 0, 0))
  43.     {
  44.         if(msg.message == WM_TIMER)
  45.         {
  46.             WaitForSingleObject(g_hFullSemaphore, INFINITE);
  47.             WaitForSingleObject(g_hMutex, INFINITE);
  48.             Consumer();
  49.             ReleaseMutex(g_hMutex);
  50.             ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);
  51.         }
  52.         else if(msg.message == WM_SETTIMER)
  53.         {
  54.             KillTimer(NULL, consumerTimerId);
  55.             consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL);
  56.         }
  57.         else
  58.         {
  59.             TranslateMessage(&msg);
  60.             DispatchMessage(&msg);
  61.         }
  62.     }
  63.     KillTimer(NULL, consumerTimerId);
  64.     return 0;
  65. }
希望各位大侠提供一个更好的解决方案。
完整的源代码在这里:
好的,以下是使用定时器线程函数实现的贪吃蛇控制台游戏的代码: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #include <time.h> #define width 20 #define height 20 int x, y, fruitX, fruitY, score; int tailX[100], tailY[100]; int nTail; enum Direction {STOP = 0, LEFT, RIGHT, UP, DOWN}; Direction dir; bool gameOver; void Setup() { srand(time(NULL)); gameOver = false; dir = STOP; x = width / 2; y = height / 2; fruitX = rand() % width; fruitY = rand() % height; score = 0; } void Draw() { system("cls"); for (int i = 0; i < width+2; i++) printf("#"); printf("\n"); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (j == 0) printf("#"); if (i == y && j == x) printf("O"); else if (i == fruitY && j == fruitX) printf("F"); else { bool print = false; for (int k = 0; k < nTail; k++) { if (tailX[k] == j && tailY[k] == i) { printf("o"); print = true; } } if (!print) printf(" "); } if (j == width - 1) printf("#"); } printf("\n"); } for (int i = 0; i < width+2; i++) printf("#"); printf("\n"); printf("Score:%d\n", score); } void Input() { if (_kbhit()) { switch (_getch()) { case 'a': dir = LEFT; break; case 'd': dir = RIGHT; break; case 'w': dir = UP; break; case 's': dir = DOWN; break; case 'x': gameOver = true; break; } } } void Logic() { int prevX = tailX[0]; int prevY = tailY[0]; int prev2X, prev2Y; tailX[0] = x; tailY[0] = y; for (int i = 1; i < nTail; i++) { prev2X = tailX[i]; prev2Y = tailY[i]; tailX[i] = prevX; tailY[i] = prevY; prevX = prev2X; prevY = prev2Y; } switch (dir) { case LEFT: x--; break; case RIGHT: x++; break; case UP: y--; break; case DOWN: y++; break; default: break; } if (x > width || x < 0 || y > height || y < 0) gameOver = true; for (int i = 0; i < nTail; i++) if (tailX[i] == x && tailY[i] == y) gameOver = true; if (x == fruitX && y == fruitY) { score += 10; fruitX = rand() % width; fruitY = rand() % height; nTail++; } } void TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { Draw(); Input(); Logic(); } DWORD WINAPI ThreadProc(LPVOID lpParam) { SetTimer(NULL, 0, 50, TimerProc); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } int main() { Setup(); HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); if (hThread) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } return 0; } ``` 上述代码使用了`SetTimer()`函数来创建定时器,并在定时器回调函数中进行游戏逻辑的更新和画面的绘制。同时,还使用线程函数`CreateThread()`和`WaitForSingleObject()`函数来启动游戏线程和等待线程结束。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值