Aracılığıyla paylaş


İptal edilmiş bir arka plan görevini işleme

Önemli API'ler

bir iptal isteğini tanıyan, çalışmayı durduran ve kalıcı depolama kullanarak iptali uygulamaya bildiren bir arka plan görevi yapmayı öğrenin.

Bu konuda, arka plan görevi giriş noktası olarak kullanılan Run yöntemi de dahil olmak üzere zaten bir arka plan görev sınıfı oluşturduğunuz varsayılır. Hızla bir arka plan görevi oluşturmaya başlamak için bkz. İşlem dışı arka plan görevi oluşturma ve kaydetme veya işlem içi arka plan görevi oluşturma ve kaydetme. Koşullar ve tetikleyiciler hakkında daha ayrıntılı bilgi için bkz. arka plan görevleriyle uygulamanızı destekleme.

Bu konu, işlem içi arka plan görevleri için de geçerlidir. Ancak Run yöntemi yerine OnBackgroundActivatedile değiştirin. Arka plan görevi ön plan uygulamanızla aynı işlemde çalıştığından, işlem içi arka plan görevleri, iptali bildirmek için kalıcı depolamayı kullanarak iptali bildirmenizi gerektirmez.

İptal isteklerini tanımak için OnCanceled yöntemini kullanın

İptal olayını işlemek için bir yöntem yazın.

Uyarı

Masaüstü dışındaki tüm cihaz aileleri için cihazın belleği azsa arka plan görevleri sonlandırılabilir. Bellek yetersizliği durumu görünür hale gelmezse veya uygulama bunu işlemezse, arka plan görevi uyarı olmadan ve OnCanceled olayı tetiklenmeden sonlandırılır. Bu, uygulamanın ön planda kullanıcı deneyimini sağlamaya yardımcı olur. Arka plan göreviniz bu senaryoyla başa çıkabilecek şekilde tasarlanmalıdır.

Aşağıdaki gibi OnCanceled adlı bir yöntem oluşturun. Bu yöntem, arka plan göreviniz için bir iptal isteği yapıldığında Windows Çalışma Zamanı tarafından çağrılan giriş noktasıdır.

private void OnCanceled(
    IBackgroundTaskInstance sender,
    BackgroundTaskCancellationReason reason)
{
    // TODO: Add code to notify the background task that it is cancelled.
}
void ExampleBackgroundTask::OnCanceled(
    Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance,
    Windows::ApplicationModel::Background::BackgroundTaskCancellationReason reason)
{
    // TODO: Add code to notify the background task that it is cancelled.
}
void ExampleBackgroundTask::OnCanceled(
    IBackgroundTaskInstance^ taskInstance,
    BackgroundTaskCancellationReason reason)
{
    // TODO: Add code to notify the background task that it is cancelled.
}

Arka plan görev sınıfına _CancelRequested adlı bir bayrak değişkeni ekleyin. Bu değişken, iptal isteğinin ne zaman yapıldığını belirtmek için kullanılır.

volatile bool _CancelRequested = false;
private:
    volatile bool m_cancelRequested;
private:
    volatile bool CancelRequested;

1. adımda oluşturduğunuz OnCanceled yönteminde, _CancelRequested bayrak değişkenini true olarak ayarlayın.

OnCanceled yöntemitam arka plan görev örneği, _CancelRequested doğru olarak ayarlar ve yararlı olabilecek hata ayıklama çıktısı yazar.

private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
    // Indicate that the background task is canceled.
    _cancelRequested = true;

    Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested...");
}
void ExampleBackgroundTask::OnCanceled(
    Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance,
    Windows::ApplicationModel::Background::BackgroundTaskCancellationReason reason)
{
    // Indicate that the background task is canceled.
    m_cancelRequested = true;
}
void ExampleBackgroundTask::OnCanceled(IBackgroundTaskInstance^ taskInstance, BackgroundTaskCancellationReason reason)
{
    // Indicate that the background task is canceled.
    CancelRequested = true;
}

Arka plan görevinin Run yönteminde, çalışmaya başlamadan önce OnCanceled olay işleyicisi yöntemini kaydedin. İşlem içi bir arka plan görevinde, bu kaydı uygulama başlatma işleminizin bir parçası olarak yapabilirsiniz. Örneğin, aşağıdaki kod satırını kullanın.

taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
taskInstance.Canceled({ this, &ExampleBackgroundTask::OnCanceled });
taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &ExampleBackgroundTask::OnCanceled);

Arka plan görevinizi sonlandırarak iptalini gerçekleştirin

bir iptal isteği alındığında, arka plan çalışmalarını yerine getiren yönteminizin, _cancelRequested trueolarak ayarlandığını fark ederek çalışmayı durdurması ve çıkış yapması gerekir. İşlem içi arka plan görevleri için bu, OnBackgroundActivated yönteminden geri dönmek anlamına gelir. İşlem dışı arka plan görevleri için bu, Run yönteminden geri dönme anlamına gelir.

Çalışırken bayrak değişkenini denetlemek için arka plan görev sınıfınızın kodunu değiştirin. _cancelRequested true olarak ayarlanırsa, çalışmanın devam etmesi durdurulur.

arka plan görevi örneği, arka plan görevi iptal edildiğinde süreölçerin düzenli geri çağırılmasını durduran bir denetim içerir.

if ((_cancelRequested == false) && (_progress < 100))
{
    _progress += 10;
    _taskInstance.Progress = _progress;
}
else
{
    _periodicTimer.Cancel();
    // TODO: Record whether the task completed or was cancelled.
}
if (!m_cancelRequested && m_progress < 100)
{
    m_progress += 10;
    m_taskInstance.Progress(m_progress);
}
else
{
    m_periodicTimer.Cancel();
    // TODO: Record whether the task completed or was cancelled.
}
if ((CancelRequested == false) && (Progress < 100))
{
    Progress += 10;
    TaskInstance->Progress = Progress;
}
else
{
    PeriodicTimer->Cancel();
    // TODO: Record whether the task completed or was cancelled.
}

Uyarı

Yukarıda gösterilen kod örneği IBackgroundTaskInstance kullanır. Arka plan görevi ilerleme durumunu kaydetmek için kullanılan progress özelliği. İlerleme, BackgroundTaskProgressEventArgs sınıfı kullanılarak uygulamaya geri bildirilir.

Çalışma durdurulduktan sonra görevin tamamlanıp tamamlanmadığını veya iptal edilip edilmediğini kaydedebilmesi için Run yöntemini değiştirin. Bu adım, işlem dışı arka plan görevleri için geçerlidir çünkü arka plan görevi iptal edildiğinde işlemler arasında iletişim kurmak için bir yönteme ihtiyacınız vardır. İşlem içi arka plan görevleri için, görevin iptal edilmiş olduğunu belirtmek için durumu uygulamayla paylaşmanız yeterlidir.

Arka plan görevi örneği LocalSettings'te durumu kaydeder.

if ((_cancelRequested == false) && (_progress < 100))
{
    _progress += 10;
    _taskInstance.Progress = _progress;
}
else
{
    _periodicTimer.Cancel();

    var settings = ApplicationData.Current.LocalSettings;
    var key = _taskInstance.Task.TaskId.ToString();

    // Write to LocalSettings to indicate that this background task ran.
    if (_cancelRequested)
    {
        settings.Values[key] = "Canceled";
    }
    else
    {
        settings.Values[key] = "Completed";
    }
        
    Debug.WriteLine("Background " + _taskInstance.Task.Name + (_cancelRequested ? " Canceled" : " Completed"));
        
    // Indicate that the background task has completed.
    _deferral.Complete();
}
if (!m_cancelRequested && m_progress < 100)
{
    m_progress += 10;
    m_taskInstance.Progress(m_progress);
}
else
{
    m_periodicTimer.Cancel();

    // Write to LocalSettings to indicate that this background task ran.
    auto settings{ Windows::Storage::ApplicationData::Current().LocalSettings() };
    auto key{ m_taskInstance.Task().Name() };
    settings.Values().Insert(key, (m_progress < 100) ? winrt::box_value(L"Canceled") : winrt::box_value(L"Completed"));

    // Indicate that the background task has completed.
    m_deferral.Complete();
}
if ((CancelRequested == false) && (Progress < 100))
{
    Progress += 10;
    TaskInstance->Progress = Progress;
}
else
{
    PeriodicTimer->Cancel();
        
    // Write to LocalSettings to indicate that this background task ran.
    auto settings = ApplicationData::Current->LocalSettings;
    auto key = TaskInstance->Task->Name;
    settings->Values->Insert(key, (Progress < 100) ? "Canceled" : "Completed");
        
    // Indicate that the background task has completed.
    Deferral->Complete();
}

Açıklamalar

Bu kod örneklerini yöntemler bağlamında görmek için arka plan görev örneğini indirebilirsiniz.

Örnek kod, açıklayıcı amaçlarlaarka plan görev örneğinden Çalıştırma yönteminin (ve geri çağırma zamanlayıcısının) yalnızca bölümlerini gösterir.

Çalıştırma yöntemi örneği

bağlam için aşağıda arka plan görev örneği çalıştır yönteminin ve zamanlayıcı geri çağırma kodunun eksiksiz gösterilmiştir.

// The Run method is the entry point of a background task.
public void Run(IBackgroundTaskInstance taskInstance)
{
    Debug.WriteLine("Background " + taskInstance.Task.Name + " Starting...");

    // Query BackgroundWorkCost
    // Guidance: If BackgroundWorkCost is high, then perform only the minimum amount
    // of work in the background task and return immediately.
    var cost = BackgroundWorkCost.CurrentBackgroundWorkCost;
    var settings = ApplicationData.Current.LocalSettings;
    settings.Values["BackgroundWorkCost"] = cost.ToString();

    // Associate a cancellation handler with the background task.
    taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);

    // Get the deferral object from the task instance, and take a reference to the taskInstance;
    _deferral = taskInstance.GetDeferral();
    _taskInstance = taskInstance;

    _periodicTimer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler(PeriodicTimerCallback), TimeSpan.FromSeconds(1));
}

// Simulate the background task activity.
private void PeriodicTimerCallback(ThreadPoolTimer timer)
{
    if ((_cancelRequested == false) && (_progress < 100))
    {
        _progress += 10;
        _taskInstance.Progress = _progress;
    }
    else
    {
        _periodicTimer.Cancel();

        var settings = ApplicationData.Current.LocalSettings;
        var key = _taskInstance.Task.Name;

        // Write to LocalSettings to indicate that this background task ran.
        settings.Values[key] = (_progress < 100) ? "Canceled with reason: " + _cancelReason.ToString() : "Completed";
        Debug.WriteLine("Background " + _taskInstance.Task.Name + settings.Values[key]);

        // Indicate that the background task has completed.
        _deferral.Complete();
    }
}
void ExampleBackgroundTask::Run(Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance)
{
    // Query BackgroundWorkCost
    // Guidance: If BackgroundWorkCost is high, then perform only the minimum amount
    // of work in the background task and return immediately.
    auto cost{ Windows::ApplicationModel::Background::BackgroundWorkCost::CurrentBackgroundWorkCost() };
    auto settings{ Windows::Storage::ApplicationData::Current().LocalSettings() };
    std::wstring costAsString{ L"Low" };
    if (cost == Windows::ApplicationModel::Background::BackgroundWorkCostValue::Medium) costAsString = L"Medium";
    else if (cost == Windows::ApplicationModel::Background::BackgroundWorkCostValue::High) costAsString = L"High";
    settings.Values().Insert(L"BackgroundWorkCost", winrt::box_value(costAsString));

    // Associate a cancellation handler with the background task.
    taskInstance.Canceled({ this, &ExampleBackgroundTask::OnCanceled });

    // Get the deferral object from the task instance, and take a reference to the taskInstance.
    m_deferral = taskInstance.GetDeferral();
    m_taskInstance = taskInstance;

    Windows::Foundation::TimeSpan period{ std::chrono::seconds{1} };
    m_periodicTimer = Windows::System::Threading::ThreadPoolTimer::CreatePeriodicTimer([this](Windows::System::Threading::ThreadPoolTimer timer)
    {
        if (!m_cancelRequested && m_progress < 100)
        {
            m_progress += 10;
            m_taskInstance.Progress(m_progress);
        }
        else
        {
            m_periodicTimer.Cancel();

            // Write to LocalSettings to indicate that this background task ran.
            auto settings{ Windows::Storage::ApplicationData::Current().LocalSettings() };
            auto key{ m_taskInstance.Task().Name() };
            settings.Values().Insert(key, (m_progress < 100) ? winrt::box_value(L"Canceled") : winrt::box_value(L"Completed"));

            // Indicate that the background task has completed.
            m_deferral.Complete();
        }
    }, period);
}
void ExampleBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance)
{
    // Query BackgroundWorkCost
    // Guidance: If BackgroundWorkCost is high, then perform only the minimum amount
    // of work in the background task and return immediately.
    auto cost = BackgroundWorkCost::CurrentBackgroundWorkCost;
    auto settings = ApplicationData::Current->LocalSettings;
    settings->Values->Insert("BackgroundWorkCost", cost.ToString());

    // Associate a cancellation handler with the background task.
    taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &ExampleBackgroundTask::OnCanceled);

    // Get the deferral object from the task instance, and take a reference to the taskInstance.
    TaskDeferral = taskInstance->GetDeferral();
    TaskInstance = taskInstance;

    auto timerDelegate = [this](ThreadPoolTimer^ timer)
    {
        if ((CancelRequested == false) &&
            (Progress < 100))
        {
            Progress += 10;
            TaskInstance->Progress = Progress;
        }
        else
        {
            PeriodicTimer->Cancel();

            // Write to LocalSettings to indicate that this background task ran.
            auto settings = ApplicationData::Current->LocalSettings;
            auto key = TaskInstance->Task->Name;
            settings->Values->Insert(key, (Progress < 100) ? "Canceled with reason: " + CancelReason.ToString() : "Completed");

            // Indicate that the background task has completed.
            TaskDeferral->Complete();
        }
    };

    TimeSpan period;
    period.Duration = 1000 * 10000; // 1 second
    PeriodicTimer = ThreadPoolTimer::CreatePeriodicTimer(ref new TimerElapsedHandler(timerDelegate), period);
}