随笔 - 55  文章 - 15  trackbacks - 0
<2013年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

     学而不思则罔,思而不学则殆,温故而知新。
     周末,老婆去上班去了(因为是2013年元旦,你知道的,休3天,上8天班,今天是上班时间),我们公司休1天,正常周末。闲来无事,想想之前写了好多东西,有时候碰到了又要重新看一遍,效率太低,还是抽个时间整理一下。于是就有了温故知新这一系列的文章。

参考文章:
     1. Windows 8 应用程序开发人员博客: 使用Windows 运行时异步性来始终保持应用程序能快速流畅地运行: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 程序设计这本书的作者说,如果写Windows 8 的书,第一章一定是异步编程(虽然它最后的书第一章不是这个),可见异步编程对于Windows 8 的重要性。本文简单介绍我对异步编程的理解吧,不对的地方请大家指正!欢迎交流。

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 是一个非抢占式的多任务环境,尽快地将控制权交还给操作系统是非常重要的)
      早期的程序员使用Timer->tick或者使用PeekMessage()定期地将控制权交还给系统。
      再后来,出现了真正的多线程,和多进程。即使一个进程不会霸占整个操作系统,但是,它还是有时会让自己不能响应外界的交互。举例来说,当你的Word执行一段费事的操作时,你任然可以打开Excel,但你不能同Word交互了。
      你可以使用多线程来完成一个需要长时间执行的任务,但是,你不能随意地执行多线程。
      每个Windows 程序都有一个UI线程来和用户进行交互,因为这个UI线程非常之重要,Windows框架允许有一个辅助线程,而且Windows的框架有一个排列辅助线程代码的机制,使得这些代码可以运行在UI线程中。
      Windows Forms中,Control都有一个BeginInvoke()方法来执行辅助线程。WPF,Silverlight和WinPhone中,每个UI对象都有一个Dispatcher属性,这是一个Dispatcher类对象,该对象都有一个BeginInvoke方法。
      Windows 8 中的方法就是使用异步编程了。

2. 异步编程和多线程的区别?

      这是我自己的疑惑,我的感觉是,异步编程是在UI线程中存在的概念,是为了实现上面所说的辅助线程用的。只不过在Windows8 中我们不使用显式的BeginInvoke()方法,而是使用了Async方法。不过有时候当一个线程想要操作UI的时候还是需要Dispatcher->RunAsync()方法。
      异步编程也是多线程的一种。

3. Windows 8 的UI策略?

      Windows 8 的UI讲究快速流畅,程序不能让用户感觉到假死的现象,如果一个UI操作(比如点击按钮代开一个文件)用时超过了50毫秒,那么用户会感觉到卡顿,影响用户体验。微软把这些可能超过50毫秒的方法全部弄成异步的,让他们运行在辅助线程中,保证UI的流畅性。

4. 怎么理解异步?

       异步就是回调,讲回调的时候都会举这么一个例子:通过电话为某人提供回拨号码。首先,为他提供回拨号码,然后挂断,做自己爱做的事情,当他把事情处理完毕,通过电话号码拨通你的电话。这就是回调,这也是异步。

5. 异步方法的使用

       考虑一下你点击一个按钮,选择打开一个文件。不同于之前的Windows 版本,现在Windows 8 中没有了打开文件夹的对话框,取而代之的是文件选择器(FilePicker),这个玩意在Windows::Storage::Pickers命名空间中。
      你要做的就是初始化一个选择器,指定打开文件的后缀名和初始地址,然后调用PickSingleFileAsync()方法。
      你已经看到了这个方法以Async结尾,这意味着它是个异步方法,有可能会超过50毫秒。异步方法一般会返回一个IAsyncOperation<T Result>^对象,T是这个方法返回的结果。
      如果你的On_Button_Clicked(...)方法中还有其他的代码的话,那么回先执行其他代码,然后,将控制权交给Windows 系统,Windows 系统会使用FilePicker打开一个文件,当打开之后,我们执行then(...)操作,也称为异步方法的延续。
      做个实验吧,验证一下异步操作的执行顺序。

 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 }
    
            经过验证,当我们的按钮按下之后,会执行这个长时间的for循环,循环执行完毕之后,才会执行另一个线程。
            我们会看到,这里使用了Create_task来包装这个IAsynOperation,Create_task方法给我的感觉就是起一个辅助线程,然后在这个线程中执行打开文件的操作。当我们执行完了PickAFileButton_Click之后,会立即执行Create_task中的方法,这时的控制权就交给了Windows 操作系统,操作系统替我们打开一个FilePicker,我们选定了一个文件之后,执行then操作。可以看到,在这个线程中,我们可以直接操作UI,为什么呢?因为所有在UI线程中执行的异步操作都是在STA中的,单线程环境,所以不用Dispatcher回UI线程中。
            在C++中我们使用Create_task().then();的方法,在C#中我们使用await关键字,更方便些。
      注意:then([]()->T Result{});中的方法依然是一个异步方法。你可以有多个延续Create_task(IAsyncOperation^ operation).then([](){}).then([](){}).then([](){});
            另外,不是所有的异步操作都能执行成功的,我们可以在then中进行异常处理。

所有的东西都被我们可爱的Concurrency::task类包办了,为什么说task类包办了呢?请看下一章,Windows 8 的异步处理(二)可爱的task.then()。你会发现,它简化了我们的很多操作,大家真的应该试一试。
     
      
posted on 2013-01-06 15:29 Dino-Tech 阅读(1738) 评论(0)  编辑 收藏 引用 所属分类: Windows 8

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理