public async Task Navigate(CancellationToken ct, INavigationRequest request) { ct = CancellationToken.None; await Task.Run(async() => { var isReleased = false; await _semaphore.WaitAsync(ct); try { var pageDefinition = _pageDefinitions.GetPageDefinition(request.PageName); var viewModel = _viewModelFactory.ResolveViewModel(pageDefinition.ViewModelType); viewModel.Initialize(request); //create tasks var setDataContext = SetPageDataContext(pageDefinition, viewModel).ToTask(ct); var navigatingTask = NotifyNavigating(ct, pageDefinition, request); var navigationIsStarted = await _dispatcherScheduler.Run(() => _frame.Navigate(pageDefinition.PageType)); if (!navigationIsStarted) { throw new InvalidOperationException("Navigation failed"); } 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); _navigatedSubject.OnNext(request); } finally { if (!isReleased) { _semaphore.Release(); isReleased = true; } } }); }