※ 引述《eric231 (嘻嘻雷梦)》之铭言:
: 各位大大好
: 目前有一个command line下的USB测试程式
: 用winapi 的方式画出一个UI
: 功能需求是想用本来在main loop 底下跑的function然后去
: 侦测event然后即时显示在listbox上
: 请问是不是需要另外用 winapi create一个tread去run本来
: main loop 底下跑的function?
: 附上程式码
: https://ideone.com/3lDWUG
你没有描述要怎样侦测 event, 就先简设是大概是
event = tcx_GetEvent(u8_Port) 吧
一般 IO 分两种情况
1. blocking
2. non-blocking
(3. asynchronous 这种先不管, 你应该暂时不会用到,
但这其实才是 event-driven 下最常见的用法)
blocking 就是 tcx_GetEvent 一定要得到一个 event 或 error,
如果没 event 就卡住, 所以叫 blocking. 这是最单纯最常见的用法
这种 case 一定要 CreateTherad, 不然 UI 卡住鼠标点下去不理你,
然后就会跳出 程式没有回应
non-blocking 就是 call 会立即传回, 如果没东西就回无.
如果是这种 case, 其实也不用 CreateThread 了.
因为没意外的话, 你的 thread function 大概也是
while (1) {
event = tcx_GetEvent(u8_Port);
// 处理 event
sleep (TIME_FOR_NEXT_EVENT);
}
那不如直接 set timer 用原本的 message loop 来处理就好了, 反而还
简单俐落些. 当然, 若要处理的事很多而影响到处理其他 UI 讯息的话,
也可以开一条 thread 来处理
以 event-driven programming 的惯用流程就是
1. 开一个 worker thread
2. 在 worker thread 里处理工作
3. 更新 UI
看推文你应该对 UI 基本概念都有了, 应该只是 WinAPI 不熟不知道怎么更新 UI?
基本上 UI 不是 thread-safe, 所以不能直接从 worker thread 操作 listbox.
惯用方法就是丢一个 message 回 UI thread 的 message queue.
而在 WinAPI 就是用 SendMessage 或 PostMessage 丢
SendMessage/PostMessage 四个参数
1. Window handle
2. Message
3. wParam
4. lParam
Window handle 是用来指定要丢进去的 message queue, 因为要丢回原本的
UI thread, 所以是填一开始 CreateWindow 的得到的 handle
Message 是想丢进去的 message, 这里应该自订一个 USB event
例如 #define WM_MY_TCX_EVENT (WM_USER+1)
wParam 和 lParam 是两个额外要和这个 event 一起丢给 message queue 的参数
他们的 size 都应至少够装一个 poiter
https://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx
以上整合起来, 在 worker thread 那端大致是这样
while (!quit) {
event = tcx_GetEvent(u8_Port);
if (event == -1)
ExitThread(-1);
else
SendMessage(hwnd, WM_MY_TCX_EVENT, event, 0);
// get next usb event
}
ExitThread(0);
而 UI 那端则是
WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
...
switch (uMsg) {
case WM_MY_TCX_EVENT:
// 处理 wParam 传来的 event
break;
}
}
另外有一些 thread synchonization 的要注意一下.
SendMessage 一般比较常用, 而他和 PostMessage 的差别是,
SendMessage 会等待该 message 被处理完才 return,
但 PostMessage 丢了就 return 了. 示意流程是这样
UI Worker
| |
| tcx_GetEvent
|<