MSG msg; while(GetMesssage(&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); }
unsigned int WINAPI ThreadFunc(LPVOID param) { ... //执行到这里,线程就准备退出了 }
unsigned int WINAPI ThreadFunc(LPVOID param) { ... while(WaitForMessage()) { DispatchMessage(); } }
class MessageLoop : public base::MessagePump::Delegate { { public: // Run the message loop. void Run(); // Signals the Run method to return after it is done processing all pending // messages. This method may only be called on the same thread that called // Run, and Run must still be on the call stack. // // Use QuitTask if you need to Quit another thread's MessageLoop, but note // that doing so is fairly dangerous if the target thread makes nested calls // to MessageLoop::Run. The problem being that you won't know which nested // run loop you are quiting, so be careful! // void Quit(); // Returns the MessageLoop object for the current thread, or null if none. static MessageLoop* current(); // The "PostTask" family of methods call the task's Run method asynchronously // from within a message loop at some point in the future. // // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed // with normal UI or IO event processing. // // The MessageLoop takes ownership of the Task, and deletes it after it has // been Run(). // // NOTE: These methods may be called on any thread. The Task will be invoked // on the thread that executes MessageLoop::Run(). void PostTask( const tracked_objects::Location& from_here, Task* task); }
MessageLoop::MessageLoop(Type type) { lazy_tls_ptr.Pointer()->Set(this); if (type_ == TYPE_DEFAULT) { pump_ = new base::MessagePumpDefault(); } else if (type_ == TYPE_IO) { pump_ = new base::MessagePumpForIO(); } else { DCHECK(type_ == TYPE_UI); pump_ = new base::MessagePumpForUI(); } } void MessageLoop::RunInternal() { pump_->Run(this); }
void MessagePumpDefault::Run(Delegate* delegate) { if (delayed_work_time_.is_null()) { event_.Wait(); } else { TimeDelta delay = delayed_work_time_ - Time::Now(); if (delay > TimeDelta()) { event_.TimedWait(delay); } else { delayed_work_time_ = Time(); } } } void MessagePumpForUI::WaitForWork() { DWORD result; result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, MWMO_INPUTAVAILABLE); if (WAIT_OBJECT_0 == result) { MSG msg = {0}; DWORD queue_status = GetQueueStatus(QS_MOUSE); if (HIWORD(queue_status) & QS_MOUSE && !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) { WaitMessage(); } return; } bool MessagePumpForIO::GetIOItem(DWORD timeout, IOItem* item) { memset(item, 0, sizeof(*item)); ULONG_PTR key = NULL; OVERLAPPED* overlapped = NULL; if (!GetQueuedCompletionStatus(port_.Get(), &item->bytes_transfered, &key, &overlapped, timeout)) { if (!overlapped) return false; // Nothing in the queue. item->error = GetLastError(); item->bytes_transfered = 0; } item->handler = reinterpret_cast<IOHandler*>(key); item->context = reinterpret_cast<IOContext*>(overlapped); return true; }
void MessagePumpDefault::ScheduleWork() { // Since this can be called on any thread, we need to ensure that our Run // loop wakes up. event_.Signal(); } void MessagePumpForUI::ScheduleWork() { PostMessage(message_hwnd_, kMsgHaveWork, reinterpret_cast<WPARAM>(this), 0); } void MessagePumpForIO::ScheduleWork() { BOOL ret = PostQueuedCompletionStatus(port_, 0, reinterpret_cast<ULONG_PTR>(this), reinterpret_cast<OVERLAPPED*>(this)); }
void MessagePumpDefault::Run(Delegate* delegate) { for (;;) { ScopedNSAutoreleasePool autorelease_pool; bool did_work = delegate->DoWork(); if (!keep_running_) break; if (did_work) continue; did_work = delegate->DoIdleWork(); if (!keep_running_) break; if (did_work) continue; if (delayed_work_time_.is_null()) { event_.Wait(); } else { TimeDelta delay = delayed_work_time_ - Time::Now(); if (delay > TimeDelta()) { event_.TimedWait(delay); } else { // It looks like delayed_work_time_ indicates a time in the past, so we // need to call DoDelayedWork now. delayed_work_time_ = Time(); } } // Since event_ is auto-reset, we don't need to do anything special here // other than service each delegate method. } keep_running_ = true; } void MessagePumpForUI::DoRunLoop() { for (;;) { bool more_work_is_plausible = ProcessNextWindowsMessage(); if (state_->should_quit) break; if (more_work_is_plausible) continue; more_work_is_plausible = state_->delegate->DoIdleWork(); if (state_->should_quit) break; if (more_work_is_plausible) continue; WaitForWork(); // Wait (sleep) until we have work to do again. } } void MessagePumpForIO::DoRunLoop() { for (;;) { bool more_work_is_plausible = state_->delegate->DoWork(); if (state_->should_quit) break; more_work_is_plausible |= WaitForIOCompletion(0, NULL); if (state_->should_quit) break; if (more_work_is_plausible) continue; more_work_is_plausible = state_->delegate->DoIdleWork(); if (state_->should_quit) break; if (more_work_is_plausible) continue; WaitForWork(); // Wait (sleep) until we have work to do again. } }
void MessageLoop::RunTask(Task* task) { task->Run(); delete task; }
some_message_loop->PostTask( some_task);
class MessagePumpForIO : public MessagePumpWin { class IOHandler { public: virtual ~IOHandler() {} // This will be called once the pending IO operation associated with // |context| completes. |error| is the Win32 error code of the IO operation // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero // on error. virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered, DWORD error) = 0; }; void RegisterIOHandler(HANDLE file_handle, IOHandler* handler); }