標籤:
在製作WP8.1手電筒的時候遇到一個問題,手電筒有時候能夠點亮有時候點不亮。
在MSDN論壇上面有人告訴我可能是優先順序的問題示意叫我使用CoreDispatcher 將task任務提高許可權,但是發現還是不行。
後來發現點亮閃關燈需要在UI線程中觸發,不能再非同步中實現,感覺和畫圖有點類似不能在非主線程中繪製圖片。
下面我就分享怎麼利用CoreDispatcher改變task任務的優先順序(不過還沒有驗證,因為我還沒有遇到需要改變優先順序的task,但是依據Windows運行時API的說明應該是正確的改變優先順序的方式)。
未改變優先順序的代碼(以枚舉攝像機啟動預覽為例):
Platform::Agile<Windows::Media::Capture::MediaCapture^> m_pCaptureManager;m_pCaptureManager = ref new Windows::Media::Capture::MediaCapture();create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture)).then([this](task<DeviceInformationCollection^> findTask){ auto myDevInfoList = findTask.get(); for (unsigned int i = 0; i < myDevInfoList->Size; i++) { auto devInfo = myDevInfoList->GetAt(i); if (devInfo->EnclosureLocation != nullptr) { if (devInfo->EnclosureLocation->Panel == Windows::Devices::Enumeration::Panel::Back) { auto settings = ref new Windows::Media::Capture::MediaCaptureInitializationSettings(); settings->VideoDeviceId = devInfo->Id; create_task(m_pCaptureManager->InitializeAsync(settings)).then([this](task<void> initTask) { initTask.get(); capture1->Source = m_pCaptureManager.Get(); create_task(m_pCaptureManager->StartPreviewAsync()).then([this](task<void> previewTask) { previewTask.get();
//不能在這裡點亮閃關燈 /*if(m_pCaptureManager->VideoDeviceController->TorchControl->Supported){ m_pCaptureManager->VideoDeviceController->TorchControl->Enaled = true; }*/ m_bPreviewing = true; }); }); } } }});
調整優先順序的代碼:
m_pCaptureManager = ref new Windows::Media::Capture::MediaCapture();create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture)).then([this](task<DeviceInformationCollection^> findTask) { auto myDevInfoList = findTask.get(); for (unsigned int i = 0; i < myDevInfoList->Size; i++)
{ auto devInfo = myDevInfoList->GetAt(i); if (devInfo->EnclosureLocation != nullptr) { if (devInfo->EnclosureLocation->Panel == Windows::Devices::Enumeration::Panel::Back) { auto settings = ref new Windows::Media::Capture::MediaCaptureInitializationSettings(); settings->VideoDeviceId = devInfo->Id; create_task(m_pCaptureManager->InitializeAsync(settings)).then([this](task<void> initTask) { initTask.get(); capture1->Source = m_pCaptureManager.Get(); create_task(m_pCaptureManager->StartPreviewAsync()).then([this](task<void> previewTask) { previewTask.get(); m_bPreviewing = true; auto myDispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; create_task(myDispatcher->RunAsync(CoreDispatcherPriority::High, ref new Windows::UI::Core::DispatchedHandler([this]() {
//不能在這裡點亮閃關燈 /*if (m_pCaptureManager->VideoDeviceController->TorchControl->Supported) { m_pCaptureManager->VideoDeviceController->TorchControl->Enabled = true; }*/ }))).then([this](task<void> RunTask) { RunTask.get(); }); }); }); } } }
});
這兩份代碼不同點就是啟動非同步預覽結束的時候
auto myDispatcher = CoreWindow::GetForCurrentThread()->Dispatcher;
create_task(myDispatcher->RunAsync(CoreDispatcherPriority::High, ref new Windows::UI::Core::DispatchedHandler([this]() {
//不能在這裡點亮閃關燈
/*if (m_pCaptureManager->VideoDeviceController->TorchControl->Supported) {
m_pCaptureManager->VideoDeviceController->TorchControl->Enabled = true;
}*/
}))).then([this](task<void> RunTask) {
RunTask.get();
});
這代碼解釋為:create_task建立一個RunTask,RunTask的任務是執行非同步對象的方法: IAsyncAction^ runasync = myDispatcher->RunAsync();即runasync的方法,這個方法帶有兩個參數:
CoreDispatcherPriority::High和ref new Windows::UI::Core::DispatchedHandler([this](){})
CoreDispatcherPriority::High 表示高優先順序
ref new Windows::UI::Core::DispatchedHandler([this](){}) 帶有功能,往這裡面添加我們需要調整優先順序去完成的功能。
所以這裡的執行順序是:create_task建立一個任務調整許可權task ---> RunAsync得到非同步對象並把非同步對象送給這個task ---> RunTask->get()執行非同步功能 ---> 在DispatchedHandler中做我們想做的事。
感覺create_task的非同步執行功能好牛逼
---恢複內容結束---
Windows 商店應用程式非同步執行task和調整task優先順序