如何處理閒置或沒有反應的背景工作
Language: HTML | XAML

如何處理閒置或沒有反應的背景工作

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

閒置背景工作會造成不必要的應用程式終止。您可透過處理取消和完全結束背景工作的方式,處理閒置 (或沒有反應) 的背景工作。

背景工作應該是短期工作,能夠快速完成它們的工作並從工作返回。這種行為是必要的,因為背景工作有嚴格的 CPU 和網路資源限制。背景工作是在應用程式暫停及連線待命期間在背景執行程式碼的唯一支援方式;資源使用限制是為了侷限背景工作可能對電池續航力造成的影響。

為了協助強制執行這些限制,背景工作基礎結構會偵測已經閒置或停止回應的背景工作。如果背景工作在最短時間內沒有利用最少量的 CPU 或網路資源配額,就會將這個背景工作視為閒置或沒有反應。最短時間的長度視系統狀態 (例如,它是否處於連線待命狀態) 而有所不同。偵測到閒置或沒有反應的背景工作時,會傳送給背景工作一個取消通知,讓背景工作有機會完全結束。如果背景工作在 5 秒內沒有完全結束以回應取消通知,就會將應用程式視為沒有回應,系統會終止它(請注意,這將會產生 WER 損毀傾印報告,您的 Windows 市集開發人員帳戶會提供這份報告)。

背景工作等待 Run() 方法中傳回非同步操作時,通常會變成閒置或沒有反應。例如,等待網路通訊端的回應,或磁碟機沒有回應時等待冗長的檔案複製操作。遵循這些步驟,即使在等待非同步操作時,仍完全取消背景工作。

您必須知道的事

技術

先決條件

  • 本主題適用於執行背景工作的應用程式。

指示

步驟 1: 登錄取消處理常式

一律為您的背景工作登錄取消處理常式。如果系統偵測到背景工作為閒置或沒有反應,它會呼叫取消處理常式。您的背景工作必須有取消處理常式,而且取消處理常式必須能夠讓工作在 5 秒內完全結束,否則您的應用程式會被終止。

步驟 2: 取消非同步操作

有些工作在等待 Run() 方法中建立的非同步操作時,看起來會像是閒置。取消所有擱置的非同步操作的簡單方式,是將單一 CancellationTokenSource 與所有非同步操作關聯。接著在您的取消處理常式中,只要在 CancellationTokenSource 上呼叫 cancel 來取消所有擱置的非同步操作。

步驟 3: 完成背景工作延遲

在 C#/C++/VB 中,背景工作必須永遠在完成工作之後在背景工作延遲物件上呼叫 Complete(),工作才能關閉。延遲上不呼叫 Complete(),背景工作就不會結束,背景工作基礎結構會偵測到它變成閒置,然後傳送取消通知給工作。

備註

閒置或沒有反應的背景工作的最佳做法

針對閒置或沒有反應的背景工作使用下列最佳做法。

  1. 一律關聯取消處理常式與您的背景工作。
  2. 在您的取消處理常式中,在 5 秒內取消所有非同步操作並返回,否則您的應用程式會被終止。
  3. 永遠在 C#/C++/VB 背景工作結束之前在背景工作延遲物件上呼叫 Complete()。

範例程式碼

下列背景工作會登錄取消處理常式、取消非同步操作以及呼叫 Complete()。


public sealed class ExampleClass:IBackgroundTask
{
    CancellationTokenSource cancelTokenSource = new CancellationTokenSource();

    async void Run(IBackgroundTaskInstance taskInstance)
    {
        BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
        HostName server = new HostName("contoso.com");
        StreamSocket sock = new StreamSocket();
        
        // Skipping other extraneous code.
        
        // Associate a cancellation handler with the background task.
        taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);

        try
        {    
            await sock.ConnectAsync(server, "http").AsTask(cancelTokenSource.Token);
            await sock.InputStream.ReadAsync(…).AsTask(cancelTokenSource.Token);                   
        }
        finally { deferral.Complete(); }
    }
    

    private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
    {
        // The background task has been detected as idle or hung.
        // Cancel all pending async operations and return from the task.
        cancelTokenSource.Cancel(); 
    }
}


相關主題

如何處理已取消的背景工作

 

 

顯示:
© 2016 Microsoft