LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message) {
	case WM_COMMAND:
		{
			switch(HIWORD(wParam)) {
			case BN_CLICKED:
				{
					gcd::queue thread_q(gcd::queue::get_current_thread_queue());
					::OutputDebugStringW(L"WINDOW THREAD\n");
					gcd::queue::get_global_queue(0, 0).after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), [=] {
						::OutputDebugStringW(L"GLOBAL THREAD\n");
						thread_q.async([] {
							::OutputDebugStringW(L"BACK ON WINDOW THREAD\n");
						});
					});
				}
				break;
			}
		}
		break;
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;

	default:
		return ::DefWindowProcW(window, message, wParam, lParam);
	}
	return 0;
}
LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message) {
	case WM_COMMAND:
		{
			switch(HIWORD(wParam)) {
			case BN_CLICKED:
				{
					gcd::queue thread_q(gcd::queue::get_current_thread_queue());
					std::wstringstream ss1;
					ss1 << L"WINDOW THREAD: " << std::hex << ::GetCurrentThreadId() << std::endl;
					::OutputDebugStringW(ss1.str().c_str());
					gcd::queue::get_global_queue(0, 0).after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), [=] {
						std::wstringstream ss2;
						ss2 << L"GLOBAL THREAD: " << std::hex << ::GetCurrentThreadId() << std::endl;
						::OutputDebugStringW(ss2.str().c_str());
						thread_q.async([] {
							std::wstringstream ss3;
							ss3 << L"BACK ON WINDOW THREAD: " << std::hex << ::GetCurrentThreadId() << std::endl;
							::OutputDebugStringW(ss3.str().c_str());
						});
					});
				}
				break;
			}
		}
		break;
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;

	default:
		return ::DefWindowProcW(window, message, wParam, lParam);
	}
	return 0;
}