2013年5月6日 星期一

[W8App] Make Native Runtime Component (1): IAsyncOperation

我自已摸索W8App半年左右,其間試過全C#或全Native C++的作法,結論是依不同的需求用不同的語法才是開發上最省力的方式,C++與XAML的結合比不上C#,而許多的Win32 API則是只有C++版本,這類的功能就必需透過建立Runtime Component與UI做結合。

開發Runtime Component時要考慮另一個重點是效能問題,由於大多只支援C++的API並不具有非同步的設計,若遇上需大量運算時會造成呼叫端「卡住」的現象。利用非同步的(IAsyncAction / IAsyncOperation)來包裝運算複雜的函式,並透過event通知呼叫端,達到良好的使用者經驗。

建立非同步的函式其實是相當容易的,首先函式的回傳值必需為IAsyncAction^ 或 IAsyncOperation<TResult>^。IAsyncAction與IAsyncOperation的差異在於IAsyncAction不回傳函式運算的結果而IAsyncOperation可回傳運算結果。若希望能回報處理的進度,則回傳值必需為IAsyncActionWithProgress<TProgress>^或IAsyncOperation<TResult, TProgress>^。

我宣告一個非同步RunProcessAsync函式如下,傳入的參數是最大的嘗試次數,回傳實際上的當試次數:

   1: namespace myProject
   2: {
   3:   public ref class myRTDLL sealed
   4:   {
   5:   public:
   6:     myRTDLL();
   7:  
   8:     Windows::Foundation::IAsyncOperation<int>^ RunProcessAsync(int maxretry);
   9:   };
  10: }

在RunProcessAsync函式中,使用create_async進行非同步程序。要注意的是return的型別必需與IAsyncOperation<TResult>^中的TResult型別一致。



   1: IAsyncOperation<int>^ myRTDLL::RunProcessAsync(int maxretry)
   2: {
   3:   return create_async([this,maxretry]() {
   4:  
   5:     int retry = 0;
   6:     for( ; retry<maxretry ; retry++)
   7:     {
   8:       if(RunProcess(retry))  break;
   9:     }
  10:  
  11:     return (retry < maxretry) ? retry : -1;
  12:   });
  13: }

呼叫端透過await等待RunProcessAsync完成運算:



   1: var asyncResult = await _myRTDLL.RunProcessAsync(10);

或是不等待RunProcessAsync的結果,同步進行其他的運算:



   1: var asyncOp = _myRTDLL.RunProcessAsync(10);
   2:  
   3: // DO SOMETHIMG
   4:  
   5: var asyncResult = await asyncOp;

以coding的量而言,把Runtime Component的函式變為非同步其實是相當簡單的…

沒有留言:

張貼留言