public void RefreshRenameSessionWithOptionsChanged(Option <bool> renameOption, bool newValue) { AssertIsForeground(); VerifyNotDismissed(); // Recompute the result only if the previous result was computed with a different flag if (_optionSet.GetOption(renameOption) != newValue) { _optionSet = _optionSet.WithChangedOption(renameOption, newValue); var cancellationToken = _cancellationTokenSource.Token; UpdateReferenceLocationsTask(ThreadingContext.JoinableTaskFactory.RunAsync(async() => { // Join prior work before proceeding, since it performs a required state update. // https://github.com/dotnet/roslyn/pull/34254#discussion_r267024593 // // The cancellation token is passed to the prior work when it starts, not when it's joined. This is // the equivalent of TaskContinuationOptions.LazyCancellation. await _allRenameLocationsTask.JoinAsync(CancellationToken.None).ConfigureAwait(false); await TaskScheduler.Default; return(await _renameInfo.FindRenameLocationsAsync(_optionSet, cancellationToken).ConfigureAwait(false)); })); } }
public void RefreshRenameSessionWithOptionsChanged(SymbolRenameOptions newOptions) { if (_options == newOptions) { return; } _threadingContext.ThrowIfNotOnUIThread(); VerifyNotDismissed(); _options = newOptions; var cancellationToken = _cancellationTokenSource.Token; UpdateReferenceLocationsTask(_threadingContext.JoinableTaskFactory.RunAsync(async() => { // Join prior work before proceeding, since it performs a required state update. // https://github.com/dotnet/roslyn/pull/34254#discussion_r267024593 // // The cancellation token is passed to the prior work when it starts, not when it's joined. This is // the equivalent of TaskContinuationOptions.LazyCancellation. await _allRenameLocationsTask.JoinAsync(CancellationToken.None).ConfigureAwait(false); await TaskScheduler.Default; return(await _renameInfo.FindRenameLocationsAsync(_options, cancellationToken).ConfigureAwait(false)); })); }
public void IsMainThreadBlockedTrueWhenAsyncOnOtherThreadBecomesSyncOnMainThread() { var nonBlockingStateObserved = new AsyncManualResetEvent(); var nowBlocking = new AsyncManualResetEvent(); JoinableTask joinableTask = null; Task.Run(delegate { joinableTask = this.Factory.RunAsync(async delegate { Assert.False(this.Context.IsMainThreadBlocked()); nonBlockingStateObserved.Set(); await Task.Yield(); await nowBlocking; Assert.True(this.Context.IsMainThreadBlocked()); }); }).Wait(); this.Factory.Run(async delegate { await nonBlockingStateObserved; joinableTask.JoinAsync().Forget(); nowBlocking.Set(); }); }
private void QueueApplyReplacements() { // If the replacement text is empty, we do not update the results of the conflict // resolution task. We instead wait for a non-empty identifier. if (this.ReplacementText == string.Empty) { return; } var cancellationToken = _conflictResolutionTaskCancellationSource.Token; var asyncToken = _asyncListener.BeginAsyncOperation(nameof(QueueApplyReplacements)); var replacementOperation = ThreadingContext.JoinableTaskFactory.RunAsync(async() => { var replacementInfo = await _conflictResolutionTask.JoinAsync(CancellationToken.None).ConfigureAwait(false); if (replacementInfo == null || cancellationToken.IsCancellationRequested) { return; } // Switch to a background thread for expensive work await TaskScheduler.Default; var computedMergeResult = await ComputeMergeResultAsync(replacementInfo, cancellationToken); await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true, cancellationToken); ApplyReplacements(computedMergeResult.replacementInfo, computedMergeResult.mergeResult, cancellationToken); }); replacementOperation.Task.CompletesAsyncOperation(asyncToken); }
// unfortunately, IVsOperationProgressStatusService requires UI thread to let project system to proceed to next stages. // this method should only be used with either await or JTF.Run, it should be never used with Task.Wait otherwise, it can // deadlock // // This method also ensures the GlobalHubClientPackage package is loaded, since brokered services in Visual // Studio require this package to provide proxy interfaces for invoking out-of-process services. public async Task WaitUntilFullyLoadedAsync(CancellationToken cancellationToken) { using ( Logger.LogBlock( FunctionId.PartialLoad_FullyLoaded, KeyValueLogMessage.NoProperty, cancellationToken ) ) { var status = await GetProgressStageStatusAsync(cancellationToken) .ConfigureAwait(false); if (status == null) { return; } var completionTask = status.WaitForCompletionAsync(); Logger.Log( FunctionId.PartialLoad_FullyLoaded, KeyValueLogMessage.Create( LogType.Trace, m => m["AlreadyFullyLoaded"] = completionTask.IsCompleted ) ); // TODO: WaitForCompletionAsync should accept cancellation directly. // for now, use WithCancellation to indirectly add cancellation await completionTask.WithCancellation(cancellationToken).ConfigureAwait(false); await _loadHubClientPackage.JoinAsync(cancellationToken).ConfigureAwait(false); } }
private void UpdateReferenceLocationsTask(JoinableTask <IInlineRenameLocationSet> findRenameLocationsTask) { AssertIsForeground(); var asyncToken = _asyncListener.BeginAsyncOperation("UpdateReferencesTask"); _allRenameLocationsTask = ThreadingContext.JoinableTaskFactory.RunAsync(async() => { var inlineRenameLocations = await findRenameLocationsTask.JoinAsync().ConfigureAwaitRunInline(); // It's unfortunate that _allRenameLocationsTask has a UI thread dependency (prevents continuations // from running prior to the completion of the UI operation), but the implementation does not currently // follow the originally-intended design. // https://github.com/dotnet/roslyn/issues/40890 await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true, _cancellationTokenSource.Token); RaiseSessionSpansUpdated(inlineRenameLocations.Locations.ToImmutableArray()); return(inlineRenameLocations); }); _allRenameLocationsTask.Task.CompletesAsyncOperation(asyncToken); UpdateConflictResolutionTask(); QueueApplyReplacements(); }
/// <summary> /// Joins a task while displaying a progress dialog. If the dialog is closed by the user /// the entire CancelableTask is canceled. /// </summary> void JoinWithProgressDialog(JoinableTask joinableTask) { taskContext.ThrowIfNotOnMainThread(); // Kick off a task that will mark the dialog as complete after joinableTask completes. var dialogTask = taskContext.Factory.RunAsync(async() => { await taskContext.Factory.SwitchToMainThreadAsync(); try { await joinableTask.JoinAsync(); } finally { progressDialog.Complete(); } }); // Display the dialog and block until it's closed. The dialog spins up its own message // pump, which allows tasks to continue executing continuations on the main thread // despite the fact that we're making a blocking call. // If dialogTask succeeds in marking the dialog as complete, it closes and ShowModal // returns true. // If the dialog is canceled by the user, it closes, ShowModal returns false, and we // cancel the task using the cancellation source. if (!progressDialog.ShowModal()) { cancellationSource.Cancel(); } dialogTask.Join(); }
async Task QueueRefreshAsync() { if (refreshJoinableTask != null) { await refreshJoinableTask.JoinAsync(); // make sure StartRefresh has completed } await(refreshJoinableTask = JoinableTaskFactory.RunAsync(RefreshAsync)); }
public async Task TestMethod1() { Thread.CurrentThread.Name = "Main1"; _control = new RoslynCodeControl(); await _f.InitializeAsync(); var c = _control; c.JTF2 = _f.JTF2; c.SourceText = ""; var w = new Window(); _window = w; w.Content = _control; JoinableTask jt1 = null; w.Loaded += (sender, args) => { jt1 = c.JTF.RunAsync(DoInput1Async); var continueWith = jt1.JoinAsync().ContinueWith(async t => { if (c.IsFaulted) { } await c.ShutdownAsync(); c.Dispatcher.InvokeShutdown(); c.SecondaryDispatcher.InvokeShutdown(); }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); }; try { w.Show(); } catch (Exception ex) { _f.Debugfn(ex.ToString()); } Dispatcher.Run(); await jt1.JoinAsync(); }
private async ValueTask <IVsOperationProgressStageStatusForSolutionLoad?> GetProgressStageStatusAsync(CancellationToken cancellationToken) { // Workaround for lack of fast path in JoinAsync; avoid calling when already completed // https://github.com/microsoft/vs-threading/pull/696 if (_progressStageStatus.Task.IsCompleted) { return(await _progressStageStatus.Task.ConfigureAwait(false)); } return(await _progressStageStatus.JoinAsync(cancellationToken).ConfigureAwait(false)); }
protected override void SettingsToPage() { ThreadHelper.JoinableTaskFactory.RunAsync( async() => { await _populateBuildServerTypeTask.JoinAsync(); await this.SwitchToMainThreadAsync(); checkBoxEnableBuildServerIntegration.SetNullableChecked(CurrentSettings.BuildServer.EnableIntegration.Value); BuildServerType.SelectedItem = CurrentSettings.BuildServer.Type.Value ?? _noneItem.Text; }); }
/// <summary> /// Try to join a task, with a timeout. /// </summary> /// <returns> /// True if the task ran to completion in the time allotted, false if the task is still /// running. /// </returns> bool TryJoin(JoinableTask joinableTask, TimeSpan timeout) { // Task.Delay is used instead of a CancellationToken because `Task.Delay(TimeSpan.Zero)` // always completes synchronously, whereas `new CancellationTokenSource(TimeSpan.Zero)` // may or may not be canceled by the time it returns. return(taskContext.Factory.Run(async() => { var task = joinableTask.JoinAsync(); if (await Task.WhenAny(Task.Delay(delay), task) == task) { await task; // Propagate exceptions return true; } return false; })); }
protected override void SettingsToPage() { ThreadHelper.JoinableTaskFactory.RunAsync( async() => { Validates.NotNull(_populateBuildServerTypeTask); await _populateBuildServerTypeTask.JoinAsync(); await this.SwitchToMainThreadAsync(); IBuildServerSettings buildServerSettings = GetCurrentSettings() .BuildServer(); checkBoxEnableBuildServerIntegration.SetNullableChecked(buildServerSettings.EnableIntegration); checkBoxShowBuildResultPage.SetNullableChecked(buildServerSettings.ShowBuildResultPage); BuildServerType.SelectedItem = buildServerSettings.Type ?? _noneItem.Text; }); }
private async Task ObserveBuildsAsync(DateTime?sinceDate, bool?running, IObserver <BuildInfo> observer, CancellationToken cancellationToken) { if (_apiClient == null) { observer.OnCompleted(); return; } try { if (_buildDefinitions == null) { _buildDefinitions = await _buildDefinitionsTask.JoinAsync(); if (_buildDefinitions == null) { observer.OnCompleted(); return; } CacheAzureDevOps = new CacheAzureDevOps { Id = CacheKey, BuildDefinitions = _buildDefinitions }; } var builds = await _apiClient.QueryBuildsAsync(_buildDefinitions, sinceDate, running); foreach (var build in builds) { observer.OnNext(CreateBuildInfo(build)); } } catch (OperationCanceledException) { // Do nothing, the observer is already stopped } catch (Exception ex) { observer.OnError(ex); } }
private void UpdateReferenceLocationsTask() { _threadingContext.ThrowIfNotOnUIThread(); var asyncToken = _asyncListener.BeginAsyncOperation("UpdateReferencesTask"); var currentOptions = _options; var currentRenameLocationsTask = _allRenameLocationsTask; var cancellationToken = _cancellationTokenSource.Token; _allRenameLocationsTask = _threadingContext.JoinableTaskFactory.RunAsync(async() => { // Join prior work before proceeding, since it performs a required state update. // https://github.com/dotnet/roslyn/pull/34254#discussion_r267024593 if (currentRenameLocationsTask != null) { await _allRenameLocationsTask.JoinAsync(cancellationToken).ConfigureAwait(false); } await TaskScheduler.Default; var inlineRenameLocations = await _renameInfo.FindRenameLocationsAsync(currentOptions, cancellationToken).ConfigureAwait(false); // It's unfortunate that _allRenameLocationsTask has a UI thread dependency (prevents continuations // from running prior to the completion of the UI operation), but the implementation does not currently // follow the originally-intended design. // https://github.com/dotnet/roslyn/issues/40890 await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true, cancellationToken); RaiseSessionSpansUpdated(inlineRenameLocations.Locations.ToImmutableArray()); return(inlineRenameLocations); }); _allRenameLocationsTask.Task.CompletesAsyncOperation(asyncToken); UpdateConflictResolutionTask(); QueueApplyReplacements(); }
private async Task ObserveBuilds(DateTime?sinceDate, bool?running, IObserver <BuildInfo> observer, CancellationToken cancellationToken) { try { if (_buildDefinitionsTask == null) { _buildDefinitionsTask = ThreadHelper.JoinableTaskFactory.RunAsync(() => _gitLabClient.Pipelines.GetAsync(ProjectName, _ => _.Scope = PipelineScope.All)); } if (_buildDefinitions == null) { _buildDefinitions = await _buildDefinitionsTask.JoinAsync(); if (_buildDefinitions == null) { observer.OnCompleted(); return; } } if (_buildDefinitions == null) { observer.OnCompleted(); return; } Func <Pipeline, bool> predicate = pipeline => running.HasValue && running.Value ? pipeline.Status == PipelineStatus.Running : pipeline.Status != PipelineStatus.Running; if (sinceDate.HasValue) { predicate += pipeline => pipeline.CreatedAt >= sinceDate; } var builds = _buildDefinitions.Where(predicate); foreach (var pipeline in builds) { var status = pipeline.Status == PipelineStatus.Running ? BuildInfo.BuildStatus.InProgress : ParseBuildStatus(pipeline.Status); var buildInfo = new BuildInfo { Id = pipeline.Id.ToString(), StartDate = pipeline.CreatedAt.Value, Status = status, CommitHashList = new List <ObjectId> { ObjectId.Parse(pipeline.Sha) }, Url = pipeline.WebUrl.ToString(), Description = $"#{pipeline.Id} {status:G}" }; observer.OnNext(buildInfo); } _buildDefinitionsTask = null; observer.OnCompleted(); } catch (OperationCanceledException) { // Do nothing, the observer is already stopped } catch (Exception e) { observer.OnError(e); } }
public Task <GitSubmoduleStatus> GetSubmoduleStatusAsync() { return(_submoduleStatus?.JoinAsync()); }
public Task <IGitHubPaneViewModel> GetViewModelAsync() => viewModelTask.JoinAsync();