public async Task Navigate(CancellationToken ct, INavigationRequest request) { await Task.Run(async() => { var isReleased = false; await _semaphore.WaitAsync(); try { var pageDefinition = _pageDefinitions.GetPageDefinition(request.PageName); var viewModel = _viewModelFactory.ResolveViewModel(pageDefinition.ViewModelType); //create tasks var setDataContext = SetPageDataContext(pageDefinition, viewModel).ToTask(); var navigatingTask = NotifyNavigating(ct, pageDefinition, request); var navigationIsStarted = await _dispatcherScheduler.Run(() => _frame.Navigate(pageDefinition.Uri)); if (!navigationIsStarted) { throw new InvalidOperationException("Navigation failed"); } viewModel.Initialize(request); await navigatingTask; var pageElement = await setDataContext; //since the navigation completed, we can let another navigation start _semaphore.Release(); isReleased = true; //add entry to history var historyEntry = new AliveNavigationHistoryEntry(request, viewModel); _history.Append(historyEntry); //list to loaded / unloaded events RegisterViewModelLoad(pageElement, viewModel); RegisterViewModelUnload(pageElement, viewModel); } finally { if (!isReleased) { _semaphore.Release(); isReleased = true; } } }); }