Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Пользователи ожидают, что приложение будет реагировать во время выполнения вычислений независимо от типа компьютера. Это означает разные вещи для разных приложений. Для некоторых это означает обеспечение более реалистичной физики, быструю загрузку данных с диска или из Интернета, быструю визуализацию сложных сцен и переход между страницами, моментальный поиск направлений или быструю обработку данных. Независимо от типа вычислений, пользователи хотят, чтобы приложение реагировало на их ввод и устраняло моменты, когда оно не отвечает, пока "думает".
Ваше приложение управляется событиями, что означает, что код выполняет работу в ответ на событие, а затем находится в состоянии простоя до следующего. Код платформы для пользовательского интерфейса (макет, входные данные, повышение событий и т. д.) и код приложения для пользовательского интерфейса выполняются в одном потоке пользовательского интерфейса. Только одна инструкция может выполняться в этом потоке одновременно, поэтому если код приложения занимает слишком много времени для обработки события, платформа не может запускать макет или создавать новые события, представляющие взаимодействие с пользователем. Скорость реагирования приложения связана с доступностью потока пользовательского интерфейса для обработки работы.
Необходимо использовать поток пользовательского интерфейса, чтобы внести почти все изменения в поток пользовательского интерфейса, включая создание типов пользовательского интерфейса и доступ к их членам. Вы не можете обновить пользовательский интерфейс из фонового потока, но вы можете опубликовать в нем сообщение с помощью CoreDispatcher.RunAsync, чтобы вызвать запуск кода.
Примечание Одно исключение заключается в том, что существует отдельный поток отрисовки, который может применять изменения пользовательского интерфейса, которые не влияют на обработку входных данных или базовый макет. Например, многие анимации и переходы, которые не влияют на макет, могут выполняться в этом потоке отрисовки.
Отложить создание экземпляра элемента
Некоторые из самых медленных этапов в приложении могут включать запуск и переключение представлений. Не делайте больше работы, чем необходимо, чтобы открыть пользовательский интерфейс, который пользователь видит изначально. Например, не создавайте пользовательский интерфейс для постепенно раскрываемого пользовательского интерфейса и содержимого всплывающих окон.
- Используйте атрибут x:Load или x:DeferLoadStrategy для отложенной инициализации элементов.
- Программно вставлять элементы в дерево по требованию.
CoreDispatcher.RunIdleAsync ставит задачи в очередь для потока пользовательского интерфейса, чтобы их обработать, когда он не занят.
Использование асинхронных API
Чтобы обеспечить реагирование приложения, платформа предоставляет асинхронные версии многих его API. Асинхронный API гарантирует, что активный поток выполнения никогда не блокируется в течение значительного времени. При вызове API из потока пользовательского интерфейса используйте асинхронную версию, если она доступна. Дополнительные сведения о программировании с использованием шаблонов асинхронного программирования см. в разделе асинхронное программирование или вызов асинхронных API в C# или Visual Basic.
Перенос работы в фоновые потоки
Напишите обработчики событий, чтобы быстро вернуться. В случаях, когда требуется выполнить нетривиальный объем работы, запланируйте его в фоновом потоке и вернитесь к выполнению основной задачи.
Вы можете асинхронно планировать работу
Помните, что к элементам пользовательского интерфейса можно обращаться только из потока пользовательского интерфейса. Используйте поток пользовательского интерфейса для доступа к элементам пользовательского интерфейса перед запуском фоновой работы и (или) используйте CoreDispatcher.RunAsync или CoreDispatcher.RunIdleAsync в фоновом потоке.
Пример работы, которую можно выполнить в фоновом потоке, — вычисление ИИ компьютера в игре. Код, вычисляющий следующий шаг компьютера, может занять много времени.
public class AsyncExample
{
private async void NextMove_Click(object sender, RoutedEventArgs e)
{
// The await causes the handler to return immediately.
await System.Threading.Tasks.Task.Run(() => ComputeNextMove());
// Now update the UI with the results.
// ...
}
private async System.Threading.Tasks.Task ComputeNextMove()
{
// Perform background work here.
// Don't directly access UI elements from this method.
}
}
Public Class AsyncExample ' ... Private Async Sub NextMove_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Await Task.Run(Function() ComputeNextMove()) ' update the UI with results End Sub Private Async Function ComputeNextMove() As Task ' ... End Function ' ... End Class
В этом примере обработчик NextMove_Click возвращается к await, чтобы поток пользовательского интерфейса оставался отзывчивым. Но выполнение снова продолжается в этом обработчике после завершения ComputeNextMove (который выполняется в фоновом потоке). Оставшийся код в обработчике обновляет пользовательский интерфейс с результатами.
Примечание Существует также ThreadPool и api ThreadPoolTimer для UWP, который можно использовать для аналогичных сценариев. Дополнительную информацию см. в разделе о многопоточности и асинхронном программировании.