项目简介和code见《同步异步和阻塞2-测试小项目》
1. 实现
1> 异步线程IO处理
unsigned CAsyncIO::ThreadWork() { int nRet = IO(); //map is better than array at here, but it need STL unsigned uTid = GetCurrentThreadId(); for (int i = 0; i < sizeof(m_uThreadArray) / sizeof(m_uThreadArray[0]); i++) { //Because handle is not same at different thread, so it need use tid to associate the thread and IO caller. if (uTid == m_uThreadArray[i]) { NotifyProgress(100, i); NotifyResult(nRet, i); } } return nRet; }
线程调用完IO后,直接通知UI结果。
2> OnStart()
bool CAsyncIO::OnStart() { OnStop(); for (int i = 0; i < sizeof(m_uThreadArray) / sizeof(m_uThreadArray[0]); i++) { HANDLE hThread = StartThread(); m_hThreadHandleArray[i] = hThread; m_uThreadArray[i] = ::GetThreadId(hThread); } return true; }
OnStart()只要把线程启动处理IO即可返回,这样就不会再阻塞UI主线程,”Start”按钮在返回后会变为”Stop”。
3> Stop的实现
由于IO不再阻塞主线程,所以“Stop”按钮变为可用,Stop的实现就变得有意义。
bool CAsyncIO::OnStop() { for (int i = 0; i < sizeof(m_hThreadHandleArray) / sizeof(m_hThreadHandleArray[0]); i++) { HANDLE hThread = m_hThreadHandleArray[i]; if (hThread) { TerminateThreadUntilExit(hThread); ::CloseHandle(hThread); m_hThreadHandleArray[i] = NULL; } } return true; }
这里Stop()的实现仅仅是简单的Terminate掉线程,由于直接终止线程,无法知道线程所处的状态,会出现什么情况无法预知,有时会出现莫名奇妙的问题,微软也是不推荐的,需谨慎使用。
2. 测试
点击”Start”按钮后,虽然IO没有处理完毕,但是按钮立即变为可用的”Stop”,同时UI窗口也是可以随意移动操作的。
异步非阻塞模式不阻塞UI主线程,用户体验上是最好的。同时在并发处理上也相对同步非阻塞模式简单,当然由于需要在IO处理完毕后通过callback通知UI主线程,这必然会涉及到线程同步的问题,线程同步是个非常头疼的问题,在异步模式带来的好处不是远远大于同步模式的情况下,其带来的问题会远远大于同步模式。
时间: 2024-10-10 00:40:11