Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
ważne interfejsy API
- Obsługa anulowania zadania w tle (BackgroundTaskCanceledEventHandler)
- IBackgroundTaskInstance
- ApplicationData.Current
Dowiedz się, jak utworzyć proces w tle, który rozpoznaje żądanie anulowania, zatrzymuje pracę i informuje aplikację o anulowaniu przy wykorzystaniu trwałej pamięci.
W tym temacie założono, że utworzono już klasę zadań w tle, w tym metodę Run , która jest używana jako punkt wejścia zadania w tle. Aby szybko rozpocząć tworzenie zadania w tle, zobacz Tworzenie i rejestrowanie zadania w tle poza procesem lub Tworzenie i rejestrowanie zadania w tle w trakcie procesu. Aby uzyskać bardziej szczegółowe informacje na temat warunków i wyzwalaczy, zobacz Support your app with background tasks (Obsługa aplikacji przy użyciu zadań w tle).
Ten temat dotyczy również zadań w tle procesu. Jednak zamiast metody Run zastąp OnBackgroundActivated. Zadania w tle uruchamiane w procesie nie wymagają używania trwałego magazynu danych do sygnalizowania anulowania, ponieważ można przekazać anulowanie przy użyciu stanu aplikacji, gdyż zadanie w tle działa w tym samym procesie co aplikacja w pierwszym planie.
Rozpoznawanie żądań anulowania przy użyciu metody OnCanceled
Napisz metodę do obsługi zdarzenia anulowania.
Uwaga / Notatka
W przypadku wszystkich rodzin urządzeń z wyjątkiem komputerów stacjonarnych, jeśli urządzenie będzie miało mało pamięci, zadania w tle mogą zostać przerwane. Jeśli nie dojdzie do wystąpienia wyjątku braku pamięci lub aplikacja go nie obsłuży, zadanie w tle zostanie zakończone bez ostrzeżenia i bez podniesienia zdarzenia OnCanceled. Pomaga to zapewnić doświadczenie użytkownika aplikacji na pierwszym miejscu. Zadanie w tle powinno być zaprojektowane tak, aby obsługiwało ten scenariusz.
Utwórz metodę o nazwie OnCanceled w następujący sposób. Ta metoda jest punktem wejścia wywoływanym przez środowisko uruchomieniowe systemu Windows po wysłaniu żądania anulowania względem zadania działającego w tle.
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.
}
Dodaj zmienną flagową o nazwie _CancelRequested do klasy zadań w tle. Ta zmienna będzie używana do wskazywania, kiedy zostało wykonane żądanie anulowania.
volatile bool _CancelRequested = false;
private:
volatile bool m_cancelRequested;
private:
volatile bool CancelRequested;
W metodzie OnCanceled utworzonej w kroku 1 ustaw zmienną flagi _CancelRequestedna true.
Pełny przykład zadania w tle w metodzie OnCanceled ustawia _CancelRequested na true i zapisuje potencjalnie przydatne dane wyjściowe do debugowania.
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;
}
W metodzie Uruchom zadania w tle przed rozpoczęciem pracy zarejestruj metodę obsługi zdarzeń OnCanceled. W zadaniu w tle wykonywanym w procesie możesz wykonać tę rejestrację jako część inicjalizacji aplikacji. Na przykład użyj następującego wiersza kodu.
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
taskInstance.Canceled({ this, &ExampleBackgroundTask::OnCanceled });
taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &ExampleBackgroundTask::OnCanceled);
Obsługuj anulowanie poprzez wyjście z zadania w tle
Po odebraniu żądania anulowania metoda, która działa w tle, musi zatrzymać pracę i zakończyć działanie, rozpoznając, kiedy _cancelRequested jest ustawiona na wartość true. W przypadku zadań w tle w trakcie procesu oznacza to powrót z metody OnBackgroundActivated. W przypadku zadań w tle poza procesem oznacza to powrót z metody Run .
Zmodyfikuj kod klasy zadań w tle, aby sprawdzić zmienną flagową podczas jej działania. Jeśli _cancelRequested zostanie ustawiona na wartość true, przestań kontynuować pracę.
Przykładowe zadanie w tle zawiera kontrolę zatrzymującą okresowe wywołanie zwrotne zegara, jeśli zadanie w tle zostało anulowane.
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.
}
Uwaga / Notatka
W przykładzie kodu pokazanym powyżej użyto IBackgroundTaskInstance.właściwość Progress używana do rejestrowania postępu zadania w tle. Postęp jest zgłaszany z powrotem do aplikacji przy użyciu klasy BackgroundTaskProgressEventArgs .
Zmodyfikuj metodę Uruchom tak, aby po zatrzymaniu pracy rejestrowała, czy zadanie zostało ukończone, czy anulowane. Ten krok dotyczy zadań w tle poza procesem, ponieważ potrzebny jest sposób komunikowania się między procesami, gdy zadanie w tle zostało anulowane. W przypadku zadań wykonywanych w tle wewnątrz procesu, można po prostu przekazać stan aplikacji, aby wskazać, że zadanie zostało anulowane.
Przykładowe zadanie w tle rejestruje stan w ustawieniach lokalnych.
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();
}
Uwagi
Można pobrać przykładowe zadanie w tle , aby zobaczyć te przykłady kodu w kontekście metod.
W celach ilustracyjnych przykładowy kod przedstawia tylko fragmenty metody Run (i timera zwrotnego) z przykładu zadania w tle .
Przykład metody uruchamiania
Pełna metoda Run oraz kod wywołania zwrotnego czasomierza z przykładowego zadania w tle pokazano poniżej jako kontekst.
// 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);
}
Tematy pokrewne
- Utwórz i zarejestruj zadanie w tle w ramach procesu.
- Tworzenie i rejestrowanie zadania w tle poza procesem
- Deklarowanie zadań w tle w manifeście aplikacji
- Wytyczne dotyczące zadań w tle
- Monitorowanie postępu i ukończenia zadania w tle
- Zarejestruj zadanie w tle
- Reagowanie na zdarzenia systemowe za pomocą zadań w tle
- Uruchamianie zadania w tle na czasomierzu
- Ustawianie warunków uruchamiania zadania w tle
- Zaktualizuj dynamiczny kafelek za pomocą zadania w tle
- Skorzystaj z wyzwalacza konserwacji
- Debugowanie zadania w tle
- Jak wyzwalać zdarzenia związane z wstrzymywaniem, wznawianiem oraz działaniem w tle w aplikacjach UWP (podczas debugowania)