我自已摸索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的函式變為非同步其實是相當簡單的…
沒有留言:
張貼留言