學(xué)而不思則罔,思而不學(xué)則殆,溫故而知新。
周末,老婆去上班去了(因?yàn)槭?013年元旦,你知道的,休3天,上8天班,今天是上班時(shí)間),我們公司休1天,正常周末。閑來(lái)無(wú)事,想想之前寫了好多東西,有時(shí)候碰到了又要重新看一遍,效率太低,還是抽個(gè)時(shí)間整理一下。于是就有了溫故知新這一系列的文章。
參考文章: 1. Windows 8 應(yīng)用程序開發(fā)人員博客: 使用Windows 運(yùn)行時(shí)異步性來(lái)始終保持應(yīng)用程序能快速流暢地運(yùn)行:http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/03/26/windows.aspx 2. Petzold的博客: Asynchronous Processing in Windows 8 http://www.charlespetzold.com/blog/2011/11/Asynchronous-Processing-in-Windows-8.html 3. MSDN WinRT的異步編程,Windows 程序設(shè)計(jì)這本書的作者說(shuō),如果寫Windows 8 的書,第一章一定是異步編程(雖然它最后的書第一章不是這個(gè)),可見異步編程對(duì)于Windows 8 的重要性。本文簡(jiǎn)單介紹我對(duì)異步編程的理解吧,不對(duì)的地方請(qǐng)大家指正!歡迎交流。
1.多線程的重要性 From the very early days of Windows programming, application developers realize that they couldn't arbitrary execute a big chunk of lengthly code.
"Windows is a nonpreemptive multitasking environment, and it is important that programs return control to Windows as quickly as possible."(Windows 是一個(gè)非搶占式的多任務(wù)環(huán)境,盡快地將控制權(quán)交還給操作系統(tǒng)是非常重要的)
早期的程序員使用Timer->tick或者使用PeekMessage()定期地將控制權(quán)交還給系統(tǒng)。
再后來(lái),出現(xiàn)了真正的多線程,和多進(jìn)程。即使一個(gè)進(jìn)程不會(huì)霸占整個(gè)操作系統(tǒng),但是,它還是有時(shí)會(huì)讓自己不能響應(yīng)外界的交互。舉例來(lái)說(shuō),當(dāng)你的Word執(zhí)行一段費(fèi)事的操作時(shí),你任然可以打開Excel,但你不能同Word交互了。
你可以使用多線程來(lái)完成一個(gè)需要長(zhǎng)時(shí)間執(zhí)行的任務(wù),但是,你不能隨意地執(zhí)行多線程。
每個(gè)Windows 程序都有一個(gè)UI線程來(lái)和用戶進(jìn)行交互,因?yàn)檫@個(gè)UI線程非常之重要,Windows框架允許有一個(gè)輔助線程,而且Windows的框架有一個(gè)排列輔助線程代碼的機(jī)制,使得這些代碼可以運(yùn)行在UI線程中。
Windows Forms中,Control都有一個(gè)BeginInvoke()方法來(lái)執(zhí)行輔助線程。WPF,Silverlight和WinPhone中,每個(gè)UI對(duì)象都有一個(gè)Dispatcher屬性,這是一個(gè)Dispatcher類對(duì)象,該對(duì)象都有一個(gè)BeginInvoke方法。
Windows 8 中的方法就是使用異步編程了。
2. 異步編程和多線程的區(qū)別?
這是我自己的疑惑,我的感覺(jué)是,異步編程是在UI線程中存在的概念,是為了實(shí)現(xiàn)上面所說(shuō)的輔助線程用的。只不過(guò)在Windows8 中我們不使用顯式的BeginInvoke()方法,而是使用了Async方法。不過(guò)有時(shí)候當(dāng)一個(gè)線程想要操作UI的時(shí)候還是需要Dispatcher->RunAsync()方法。
異步編程也是多線程的一種。
3. Windows 8 的UI策略?
Windows 8 的UI講究快速流暢,程序不能讓用戶感覺(jué)到假死的現(xiàn)象,如果一個(gè)UI操作(比如點(diǎn)擊按鈕代開一個(gè)文件)用時(shí)超過(guò)了50毫秒,那么用戶會(huì)感覺(jué)到卡頓,影響用戶體驗(yàn)。微軟把這些可能超過(guò)50毫秒的方法全部弄成異步的,讓他們運(yùn)行在輔助線程中,保證UI的流暢性。
4. 怎么理解異步?
異步就是回調(diào),講回調(diào)的時(shí)候都會(huì)舉這么一個(gè)例子:通過(guò)電話為某人提供回?fù)芴?hào)碼。首先,為他提供回?fù)芴?hào)碼,然后掛斷,做自己愛做的事情,當(dāng)他把事情處理完畢,通過(guò)電話號(hào)碼撥通你的電話。這就是回調(diào),這也是異步。
5. 異步方法的使用
考慮一下你點(diǎn)擊一個(gè)按鈕,選擇打開一個(gè)文件。不同于之前的Windows 版本,現(xiàn)在Windows 8 中沒(méi)有了打開文件夾的對(duì)話框,取而代之的是文件選擇器(FilePicker),這個(gè)玩意在Windows::Storage::Pickers命名空間中。
你要做的就是初始化一個(gè)選擇器,指定打開文件的后綴名和初始地址,然后調(diào)用PickSingleFileAsync()方法。
你已經(jīng)看到了這個(gè)方法以Async結(jié)尾,這意味著它是個(gè)異步方法,有可能會(huì)超過(guò)50毫秒。異步方法一般會(huì)返回一個(gè)IAsyncOperation<T Result>^對(duì)象,T是這個(gè)方法返回的結(jié)果。
如果你的On_Button_Clicked(...)方法中還有其他的代碼的話,那么回先執(zhí)行其他代碼,然后,將控制權(quán)交給Windows 系統(tǒng),Windows 系統(tǒng)會(huì)使用FilePicker打開一個(gè)文件,當(dāng)打開之后,我們執(zhí)行then(...)操作,也稱為異步方法的延續(xù)。
做個(gè)實(shí)驗(yàn)吧,驗(yàn)證一下異步操作的執(zhí)行順序。
1 void Scenario1::PickAFileButton_Click(Object^ sender, RoutedEventArgs^ e)
2 {
3 // Clear previous returned file name, if it exists, between iterations of this scenario
4 rootPage->ResetScenarioOutput(OutputTextBlock);
5
6 if (rootPage->EnsureUnsnapped())
7 {
8 FileOpenPicker^ openPicker = ref new FileOpenPicker();
9 openPicker->ViewMode = PickerViewMode::Thumbnail;
10 openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
11 openPicker->FileTypeFilter->Append(".jpg");
12 openPicker->FileTypeFilter->Append(".jpeg");
13 openPicker->FileTypeFilter->Append(".png");
14
15 create_task(openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
16 {
17 if (file)
18 {
19 OutputTextBlock->Text = "Picked photo: " + file->Name;
20 }
21 else
22 {
23 OutputTextBlock->Text = "Operation cancelled.";
24 }
25 }).then([this](task<void> t)
26 {
27 try{
28 t.get();
29 }catch(Platform::Exception^ e)
30 {
31 OutputTextBlock->Text = e->Message;
32 }
33 });
34 for(int i = 0 ; i < 1000000000; i++)
35 {
36 int j = 0;
37 j++;
38 }
39 int k = 0;
40 k++;
41 }
42 }
經(jīng)過(guò)驗(yàn)證,當(dāng)我們的按鈕按下之后,會(huì)執(zhí)行這個(gè)長(zhǎng)時(shí)間的for循環(huán),循環(huán)執(zhí)行完畢之后,才會(huì)執(zhí)行另一個(gè)線程。
我們會(huì)看到,這里使用了Create_task來(lái)包裝這個(gè)IAsynOperation,Create_task方法給我的感覺(jué)就是起一個(gè)輔助線程,然后在這個(gè)線程中執(zhí)行打開文件的操作。當(dāng)我們執(zhí)行完了PickAFileButton_Click之后,會(huì)立即執(zhí)行Create_task中的方法,這時(shí)的控制權(quán)就交給了Windows 操作系統(tǒng),操作系統(tǒng)替我們打開一個(gè)FilePicker,我們選定了一個(gè)文件之后,執(zhí)行then操作。可以看到,在這個(gè)線程中,我們可以直接操作UI,為什么呢?因?yàn)樗性赨I線程中執(zhí)行的異步操作都是在STA中的,單線程環(huán)境,所以不用Dispatcher回UI線程中。
在C++中我們使用Create_task().then();的方法,在C#中我們使用await關(guān)鍵字,更方便些。
注意:then([]()->T Result{});中的方法依然是一個(gè)異步方法。你可以有多個(gè)延續(xù)Create_task(IAsyncOperation^ operation).then([](){}).then([](){}).then([](){});
另外,不是所有的異步操作都能執(zhí)行成功的,我們可以在then中進(jìn)行異常處理。
所有的東西都被我們可愛的Concurrency::task類包辦了,為什么說(shuō)task類包辦了呢?請(qǐng)看下一章,Windows 8 的異步處理(二)可愛的task.then()。你會(huì)發(fā)現(xiàn),它簡(jiǎn)化了我們的很多操作,大家真的應(yīng)該試一試。
posted on 2013-01-06 15:29
Dino-Tech 閱讀(1748)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
Windows 8