2013-09-21 42 views
2

在Windows商店应用块下面的代码运行的UI 30秒,尽管这个循环还应当在一个单独的线程中运行:为什么线程池工作项目在UI线程上执行?

int seconds(30); 
// Create a thread pool 
ComPtr<IThreadPoolStatics> threadPool; 
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), &threadPool); 
// 
// Create an asynchronous task and start it 
ComPtr<ABI::Windows::Foundation::IAsyncAction> asyncActionPtr; 
hr = threadPool->RunAsync(Callback<IWorkItemHandler>(// Line 1 
    // 
    // Lambda for task. Loops doing nothing until 30 seconds have passed 
    [seconds](ABI::Windows::Foundation::IAsyncAction* asyncAction) -> HRESULT { 
     std::chrono::system_clock::time_point end(std::chrono::system_clock::now() + std::chrono::seconds(seconds)); // Line 3 
     while (std::chrono::system_clock::now() < end); 
    return S_OK; // Line 4 
}).Get(), &asyncActionPtr); 
if (FAILED(hr)) throw std::exception("Cannot start thread"); // Line 2 

当我设置的标线断点,我可以看到,第1行命中第2行,然后是第3行,之后是第3行30秒。在这30秒内,UI被阻止,并且Visual Studio中的线程视图为所有断点显示相同的线程(SHcore.dll)。 我正在使用Windows 8和Visual Studio 2012. 有人可以解释吗?

回答

2

Bill Messmer给出了MSDN的完美答案。总之:

由Callback创建的委托对象不是敏捷的,这意味着它不能传递给线程池线程。相反,该线程收到一个代理并将其调用回UI线程中的delgate对象。比尔还为这个问题提供了一个简单的解决方案。