【Win 10 應用開發】在App所在的進程中執行背景工作

來源:互聯網
上載者:User

標籤:

在以往版本中,背景工作都是以獨立的專用進程來運行,因此,定義背景工作代碼的類型都要位於 Windows 運行時組件項目中。

不過,在14393中,SDK 作了相應的擴充,不僅支援以前的獨立進程中運行背景工作,也允許背景工作與應用程式位於同一個進程中執行,即單進程背景工作(Single – Process)。

聽起來很高深?其實很Easy,和以往的多進程模式的背景工作差不多,只是有以下兩點不同:

  1. 對於獨立進程的背景工作,實現方法是實現 IBackgroundTask 介面,然後實現 Run 方法;而如果你希望讓背景工作在應用所在的進程中執行,可以重寫 Application 類的 OnBackgroundActivated 方法就可以了,它類似於 IBackgroundTask 的 Run 方法。在OnBackgroundActivated方法中,你可以通過方法參數獲得一個IBackgroundTaskInstance執行個體,所以與Run方法的處理是一樣的。
  2. 在配置資訊清單檔時,獨立進程中執行的背景工作是必須指明進入點的,即背景工作類的類型名,包含命名空間路徑。而如果背景工作是在應用進程中執行的話,就不需要指點進入點,因為背景工作的進入點與應用相同,就是App類。

 

只要明白了以上兩點,你就明白了95%了,剩下的5%,就等老周來示範給大夥瞧吧。

App Service 的實現跟背景工作差不多,本次表演,老周就選用AppService來試水吧。

這個樣本只有小學二年級水平,它分為兩個應用,一個應用具備app service,另一個應用調用它。service的功能是計算兩個整數的乘積,所以說是小學二年級水平。

先看app service的應用實現,項目模板會為我們產生一個App類,基類是Application,很簡單,直接重寫OnBackgroundActivated方法就行了。

 

        protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)        {            ……        }

 

這個方法就相當於Run方法,所以,和以前一樣,在其中添加處理代碼。

            IBackgroundTaskInstance taskInstance = args.TaskInstance;            var taskDef = taskInstance.GetDeferral();            taskInstance.Canceled += (ca, cb) => taskDef.Complete();            if (taskInstance.TriggerDetails != null && taskInstance.TriggerDetails is AppServiceTriggerDetails)            {                AppServiceTriggerDetails details = taskInstance.TriggerDetails as AppServiceTriggerDetails;                string appsvName = details.Name;                if (appsvName == "my.multip")                {                    AppServiceConnection conn = details.AppServiceConnection;                    conn.RequestReceived += async (r1, r2) =>                    {                        var svdef = r2.GetDeferral();                        var request = r2.Request;                        ValueSet inputs = request.Message;                        int x = Convert.ToInt32(inputs["a"]);                        int y = Convert.ToInt32(inputs["b"]);                        int o = x * y;                        ValueSet sendBack = new ValueSet();                        sendBack["r"] = o;                        await request.SendResponseAsync(sendBack);                        svdef.Complete();                        taskDef.Complete();                    };                    conn.ServiceClosed += (k1, k2) =>                    {                        Debug.WriteLine("app service串連關閉。");                        taskDef.Complete();                    };                }            }

 

 

然後就完事了,注意在資訊清單檔中,不要指定進入點了。

      <Extensions>        <uap:Extension Category="windows.appService">          <uap:AppService Name="my.multip" />        </uap:Extension>      </Extensions>

 

 

現在可以在另一個應用中調用了。

            AppServiceConnection conn = new AppServiceConnection();            conn.AppServiceName = "my.multip";            conn.PackageFamilyName = txtPkname.Text;            var state = await conn.OpenAsync();            if (state == AppServiceConnectionStatus.Success)            {                ValueSet input = new ValueSet();                input["a"] = ComputeObject.Num1;                input["b"] = ComputeObject.Num2;                var response = await conn.SendMessageAsync(input);                if (response.Status == AppServiceResponseStatus.Success)                {                    ValueSet res = response.Message;                    ComputeObject.Result = Convert.ToInt32(res["r"]);                }            }

 

調用App Service 時,先new一個AppServiceConnection,然後指定包含app service的應用的Package的名字,這個包名可以用以下方法來擷取:

  • 在包含app service的應用中,訪問這個靜態屬性擷取:Windows.ApplicationModel.Package.Current.Id.FamilyName。
  • 用VS產生項目,然後開啟【輸出】視窗,顯示來源選擇“產生”,這樣你就能看到包含應用服務的應用程式套件名了。如。

 

不能使用資訊清單檔中的包名,因為那個包名不完整。不過,你得注意了,通過【輸出】視窗擷取包名的時候,包的名字中要去掉版本號碼和平台描述,比如,我的項目中輸出的產生的包名為:

62da1ba5-7faf-4109-b82a-7a6027dbc3a3_1.0.0.0_x86__6pcpwfmxf0rfc

 

其中,1.0.0.0是版本號碼,要去掉,x86是平台描述,也要幹掉,後面的6pcpwfmxf0rfc可能是開發人員的標識,不能去掉。最終得到需要的包名為:

62da1ba5-7faf-4109-b82a-7a6027dbc3a3_6pcpwfmxf0rfc

前面的GUID是應用程式套件名字,後面要接一個底線,然後是6pcpwfmxf0rfc。

 

把這個最終取得的名字賦值給AppServiceConnection的PackageFamilyName屬性即可,AppServiceName屬性工作表示要調用的app service的名字。

準備好參數後,調用OpenAsync方法開啟串連,一定要先開啟串連,才能調用應用服務。使用SendMessageAsync方法發送輸入參數,參數是一個ValueSet對象,其實是個字典,可以自訂參數結構。在本例中,既然要計算乘法運算,當然是要傳遞兩個整數值了。

SendMessageAsync方法調用後,會非同步返回一個AppServiceResponse執行個體,該執行個體中包含著一些從應用服務返回的內容,訪問Message屬性就得到應用服務響應的ValueSet,並可從中取出需要的資料,該例子中,是取出計算結果。

好,項目幹完了,咱們來試試,同時運行兩個應用,然後試著調用一下應用服務。

 

 

效果已達到, 這時候,大夥可能會疑惑,如果包含app serivce的應用進程退出後,還能調用應用服務嗎?沒事,許多事情就是試出來的,試試看。把包含應用服務的應用進程結束掉,然後再調用一次,發現是可以成功調用的。

有了這一招,定義背景工作就靈活很多了,既可以在獨立進程中完成,也可以在應用進程中完成,具體採用哪一種,就看實際情況了。一切東西都是靈活運用的,千萬不要把技術學死了。那些整天吃飽了撐著,想把什麼東西都變成公式化的思想是幼稚的、死板的,這個世界上,不可以量化的事情多得很。

不過,老周可以發表一些低見,僅作參考。如果背景工作的觸發源與應用程式關係不大,比如使用者登入/登出時執行的,每隔一段時間執行的(定時),這些情況,建議把背景工作寫到獨立的Windows運行時組件項目中,讓它以獨立的進程進行。

要是背景工作是應用程式主動觸發的,比如後台轉碼(音/視頻處理),或者由應用程式使用Application Trigger觸發的背景工作,都可以考慮把它歸入應用程式進程中,即本文所講述的情況。

 

好了,今天的牛逼吹完了,該去喝點茶了(白開水最好喝,集天地靈氣,無雜質,無負作用),下一篇文章咱們聊聊開機前的事情。

樣本原始碼下載

 

 

【Win 10 應用開發】在App所在的進程中執行背景工作

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.