private void UpdateConflictResolutionTask() { AssertIsForeground(); _conflictResolutionTaskCancellationSource.Cancel(); _conflictResolutionTaskCancellationSource = new CancellationTokenSource(); // 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 replacementText = this.ReplacementText; var optionSet = _optionSet; var cancellationToken = _conflictResolutionTaskCancellationSource.Token; var asyncToken = _asyncListener.BeginAsyncOperation(nameof(UpdateConflictResolutionTask)); _conflictResolutionTask = 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 cancellation of the conflict resolution task is requested before the rename locations task // completes, we do not need to wait for rename before cancelling. The next conflict resolution task // will wait on the latest rename location task if/when necessary. var result = await _allRenameLocationsTask.JoinAsync(cancellationToken).ConfigureAwait(false); await TaskScheduler.Default; return(await result.GetReplacementsAsync(replacementText, optionSet, cancellationToken).ConfigureAwait(false)); }); _conflictResolutionTask.Task.CompletesAsyncOperation(asyncToken); }
public override void StopListening() { _foregroundDispatcher.AssertForegroundThread(); if (_fileChangeAdviseTask == null || _fileChangeUnadviseTask?.IsCompleted == false) { // Already not listening or trying to stop listening return; } _fileChangeUnadviseTask = _joinableTaskFactory.RunAsync(async() => { try { var fileChangeCookie = await _fileChangeAdviseTask; if (fileChangeCookie == VSConstants.VSCOOKIE_NIL) { // Wasn't able to listen for file change events. This typically happens when some sort of exception (i.e. access exceptions) // is thrown when attempting to listen for file changes. return; } await _fileChangeService.UnadviseFileChangeAsync(fileChangeCookie); _fileChangeAdviseTask = null; } catch (PathTooLongException) { // Don't report PathTooLongExceptions but don't fault either. } catch (Exception exception) { _errorReporter.ReportError(exception); } }); }
protected override void OnTransitionedToMainThread(JoinableTask joinableTask, bool canceled) { base.OnTransitionedToMainThread(joinableTask, canceled); this.OnTransitionedToMainThreadCallback?.Invoke(joinableTask, canceled); }
protected override void OnTransitioningToMainThread(JoinableTask joinableTask) { base.OnTransitioningToMainThread(joinableTask); this.OnTransitioningToMainThreadCallback?.Invoke(joinableTask); }
/// <summary> /// Adds the given AggregateConfiguration, CohortAggregateContainer or JoinableCohortAggregateConfiguration to the compiler Task list or returns the existing /// ICompileable if it is already part of the Compilation list. This will not start the task, you will have to call Launch... to start the ICompileable executing /// </summary> /// <param name="runnable">An AggregateConfiguration, CohortAggregateContainer or JoinableCohortAggregateConfiguration you want to schedule for execution</param> /// <param name="globals"></param> /// <returns></returns> public ICompileable AddTask(IMapsDirectlyToDatabaseTable runnable, IEnumerable <ISqlParameter> globals) { var aggregate = runnable as AggregateConfiguration; var container = runnable as CohortAggregateContainer; var joinable = runnable as JoinableCohortAggregateConfiguration; if (aggregate == null && container == null && joinable == null) { throw new NotSupportedException( "Expected c to be either AggregateConfiguration or CohortAggregateContainer but it was " + runnable.GetType().Name); } CancellationTokenSource source = new CancellationTokenSource(); ICompileable task; //thing that will produce the SQL CohortQueryBuilder queryBuilder; CohortQueryBuilder cumulativeQueryBuilder = null; CohortAggregateContainer parent; //if it is an aggregate if (aggregate != null) { //which has a parent task = new AggregationTask(aggregate, this); queryBuilder = new CohortQueryBuilder(aggregate, globals); parent = aggregate.GetCohortAggregateContainerIfAny(); } else if (joinable != null) { task = new JoinableTask(joinable, this); queryBuilder = new CohortQueryBuilder(joinable.AggregateConfiguration, globals, true); parent = null; } else { task = new AggregationContainerTask(container, this); queryBuilder = new CohortQueryBuilder(container, globals); parent = container.GetParentContainerIfAny(); } //if there is a parent if (parent != null) { //tell the task what the container is for UI purposes really bool isFirstInContainer = parent.GetOrderedContents().First().Equals(runnable); task.SetKnownContainer(parent, isFirstInContainer); //but... //if the container/aggregate being processed isn't the first component in the container if (!isFirstInContainer && IncludeCumulativeTotals) //and we want cumulative totals { cumulativeQueryBuilder = new CohortQueryBuilder(parent, globals); cumulativeQueryBuilder.StopContainerWhenYouReach = (IOrderable)runnable; } } ExternalDatabaseServer cacheServer = null; //if the overall owner has a cache configured if (CohortIdentificationConfiguration.QueryCachingServer_ID != null) { cacheServer = CohortIdentificationConfiguration.QueryCachingServer; queryBuilder.CacheServer = cacheServer; if (cumulativeQueryBuilder != null) { cumulativeQueryBuilder.CacheServer = cacheServer; } } //setup cancellation task.CancellationToken = source.Token; string newsql = ""; string cumulativeSql = ""; try { //get the count(*) SQL newsql = queryBuilder.SQL; if (cumulativeQueryBuilder != null) { cumulativeSql = cumulativeQueryBuilder.SQL; } } catch (QueryBuildingException e) { //it was not possible to generate valid SQL for the task task.CrashMessage = e; task.State = CompilationState.Crashed; } //we have seen this entity before (by ID & entity type) KeyValuePair <ICompileable, CohortIdentificationTaskExecution> existingTask; if (joinable != null) { existingTask = Tasks.SingleOrDefault((kvp => kvp.Key.Child.Equals(joinable))); } else if (aggregate != null) { existingTask = Tasks.SingleOrDefault(kvp => kvp.Key.Child.Equals(aggregate)); } else { existingTask = Tasks.SingleOrDefault(kvp => kvp.Key.Child.Equals(container)); } //job already exists (this is the same as saying existingTask!=null) if (!existingTask.Equals(default(KeyValuePair <ICompileable, CohortIdentificationTaskExecution>))) { if (existingTask.Value.CountSQL.Equals(newsql)) { //The SQl is the same but the order or cached if (existingTask.Key.Order != task.Order)//do not delete this if statement, it prevents rewrites to the database where Order asignment has side affects { existingTask.Key.Order = task.Order; } return(existingTask.Key); //existing task has the same SQL } else { //it is different so cancel the old one existingTask.Value.Cancel(); //throw away the old task Tasks.Remove(existingTask.Key); //dispose of any resources it's holding onto existingTask.Value.Dispose(); } } var isResultsForRootContainer = container != null && container.ID == CohortIdentificationConfiguration.RootCohortAggregateContainer_ID; var taskExecution = new CohortIdentificationTaskExecution(cacheServer, newsql, cumulativeSql, source, queryBuilder.CountOfSubQueries, queryBuilder.CountOfCachedSubQueries, isResultsForRootContainer); //create a new task Tasks.Add(task, taskExecution); return(task); }
protected override void OnTransitionedToMainThread(JoinableTask joinableTask, bool canceled) { this.addToLog(FactoryLogEntry.OuterOnTransitionedToMainThread); base.OnTransitionedToMainThread(joinableTask, canceled); }
protected override void OnTransitioningToMainThread(JoinableTask joinableTask) { this.addToLog(FactoryLogEntry.OuterOnTransitioningToMainThread); base.OnTransitioningToMainThread(joinableTask); }
internal void SetSubmoduleStatus(JoinableTask <GitSubmoduleStatus> status) { _submoduleStatus = status; }
public TaskAwaiter(JoinableTask task) { awaiter = task.GetAwaiter(); }
public JoinableTaskAwaitable(JoinableTask task) { this.task = task; }
public void RegisterCriticalAsyncTask(JoinableTask joinableTask, bool registerFaultHandler = false) { }
public void RegisterAsyncTask(JoinableTask joinableTask, ProjectCriticalOperation operationFlags, bool registerFaultHandler = false) { }
/// <summary> /// Schedules work to be done on the background, /// potentially preempted by another piece of work scheduled in the future, /// <paramref name="updateUi" /> indicates whether a single piece of work should occue once all background work is completed. /// </summary> public void Enqueue(Func <TModel, CancellationToken, Task <TModel> > transformation, bool updateUi) { // The integrity of our sequential chain depends on this method not being called concurrently. // So we require the UI thread. if (!_joinableTaskFactory.Context.IsOnMainThread) { throw new InvalidOperationException($"This method must be callled on the UI thread."); } if (_token.IsCancellationRequested || _terminated) { return; // Don't enqueue after computation has stopped. } // Attempt to commit (CommitIfUnique) will cancel the UI updates. If the commit failed, we still want to update the UI. if (_uiCancellation.IsCancellationRequested) { _uiCancellation = new CancellationTokenSource(); } var previousTask = _lastJoinableTask; JoinableTask <TModel> currentTask = null; currentTask = _joinableTaskFactory.RunAsync(async() => { await Task.Yield(); // Yield to guarantee that currentTask is assigned. await _computationTaskScheduler; // Go to the above priority thread. Main thread will return as soon as possible. try { var previousModel = await previousTask; if (_token.IsCancellationRequested || _terminated) { return(previousModel); } // Previous task finished processing. We are ready to execute next piece of work. var transformedModel = await transformation(previousModel, _token).ConfigureAwait(true); RecentModel = transformedModel; // TODO: Consider updating UI even if updateUi is false but it wasn't updated yet. if (_lastJoinableTask == currentTask && !_token.IsCancellationRequested && !_terminated) { _callbacks.ComputationFinished(transformedModel); if (updateUi && !_uiCancellation.IsCancellationRequested) { _callbacks.UpdateUI(transformedModel, _uiCancellation.Token).Forget(); } } return(transformedModel); } catch (Exception ex) when(ex is OperationCanceledException || ex is ThreadAbortException) { // Disallow enqueuing more tasks _terminated = true; // Close completion _callbacks.DismissDueToCancellation(); // Return a task that has not faulted return(default(TModel)); } catch (Exception ex) { // Disallow enqueuing more tasks _terminated = true; // Log the issue _guardedOperations.HandleException(this, ex); // Close completion _callbacks.DismissDueToError(); // Return a task that has not faulted return(default(TModel)); } }); _lastJoinableTask = currentTask; }
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 <T> LoadedProjectAsync <T>(Func <Task <T> > action) { JoinableTask <T> joinable = _tasksService.LoadedProjectAsync(action); return(joinable.Task); }
public static void FileAndForget(this JoinableTask joinableTask, Func <Exception, bool> fileOnlyIf = null) { joinableTask.Task.FileAndForget(fileOnlyIf); }
/// <summary> /// Logs error information to the Output Window if the given <see cref="JoinableTask" /> faults. /// </summary> /// <remarks> /// This is the JoinableTask equivalent of <see cref="FireAndForget(System.Threading.Tasks.Task, bool)"/> /// </remarks> public static void FireAndForget(this JoinableTask joinableTask, bool logOnFailure = true) { FireAndForget(joinableTask.Task, logOnFailure); }
/// <summary> /// A helper method that just blocks on the completion of a JoinableTask. /// </summary> /// <remarks> /// This method is explicitly defined rather than using an anonymous method because /// we do NOT want the calling method's name embedded into this method's name by the compiler /// so that we can verify based on method name. /// </remarks> private static void OnHangDetected_BlockingMethodHelper(JoinableTask jt) { jt.Join(); }
public Service( IAsyncServiceProvider2 serviceProvider, IThreadingContext threadingContext, IAsynchronousOperationListener listener ) { _serviceProvider = serviceProvider; _threadingContext = threadingContext; _loadHubClientPackage = _threadingContext.JoinableTaskFactory.RunAsync( async() => { // Use the disposal token, since the caller's cancellation token will apply instead to the // JoinAsync operation in GetProgressStageStatusAsync. await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync( alwaysYield: true, _threadingContext.DisposalToken ); // Make sure the HubClient package is loaded, since we rely on it for proffered OOP services var shell = await _serviceProvider .GetServiceAsync <SVsShell, IVsShell7>() .ConfigureAwait(true); Assumes.Present(shell); await shell.LoadPackageAsync(Guids.GlobalHubClientPackageGuid); } ); _progressStageStatus = _threadingContext.JoinableTaskFactory.RunAsync( async() => { // pre-emptively make sure event is subscribed. if APIs are called before it is done, calls will be blocked // until event subscription is done using var asyncToken = listener.BeginAsyncOperation( "StatusChanged_EventSubscription" ); await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync( alwaysYield: true, _threadingContext.DisposalToken ); var service = await serviceProvider .GetServiceAsync < SVsOperationProgress, IVsOperationProgressStatusService >(throwOnFailure: false) .ConfigureAwait(true); if (service is null) { return(null); } var status = service.GetStageStatusForSolutionLoad( CommonOperationProgressStageIds.Intellisense ); status.PropertyChanged += (_, _) => StatusChanged?.Invoke(this, EventArgs.Empty); return(status); } ); }