private async Task HandleFileChangedAsync(CancellationToken cancellationToken = default) { try { // Only notify the project if the contents of the watched file have changed. // In the case if we fail to read the contents, we will opt to notify the project. byte[] newHash = GetFileHashOrNull(_fileBeingWatched); if (newHash == null || _previousContentsHash == null || !newHash.SequenceEqual(_previousContentsHash)) { TraceUtilities.TraceVerbose("{0} changed on disk. Marking project dirty", _fileBeingWatched); _previousContentsHash = newHash; cancellationToken.ThrowIfCancellationRequested(); await _projectServices.Project.Services.ProjectAsynchronousTasks.LoadedProjectAsync(async() => { await _projectServices.ProjectAccessor.EnterWriteLockAsync(async(collection, token) => { // notify all the loaded configured projects IEnumerable <ConfiguredProject> currentProjects = _projectServices.Project.LoadedConfiguredProjects; foreach (ConfiguredProject configuredProject in currentProjects) { await _projectServices.ProjectAccessor.OpenProjectForWriteAsync(configuredProject, project => { project.MarkDirty(); configuredProject.NotifyProjectChange(); }, cancellationToken).ConfigureAwait(true); // Stay on same thread that took lock } }, cancellationToken).ConfigureAwait(true); // Stay on same thread that took lock }); } else { TraceUtilities.TraceWarning("{0} changed on disk, but has no actual content change.", _fileBeingWatched); } } catch (OperationCanceledException) { // Project is already unloaded } }
private async Task HandleFileChangedAsync(CancellationToken cancellationToken = default(CancellationToken)) { try { // Only notify the project if the contents of the watched file have changed. // In the case if we fail to read the contents, we will opt to notify the project. byte[] newHash = GetFileHashOrNull(_fileBeingWatched); if (newHash == null || _previousContentsHash == null || !newHash.SequenceEqual(_previousContentsHash)) { TraceUtilities.TraceVerbose("{0} changed on disk. Marking project dirty", _fileBeingWatched); _previousContentsHash = newHash; cancellationToken.ThrowIfCancellationRequested(); await _projectServices.Project.Services.ProjectAsynchronousTasks.LoadedProjectAsync(async() => { using (var access = await _projectServices.ProjectLockService.WriteLockAsync(cancellationToken)) { // notify all the loaded configured projects var currentProjects = _projectServices.Project.LoadedConfiguredProjects; foreach (var configuredProject in currentProjects) { // Inside a write lock, we should get back to the same thread. var project = await access.GetProjectAsync(configuredProject, cancellationToken).ConfigureAwait(true); project.MarkDirty(); configuredProject.NotifyProjectChange(); } } }); } else { TraceUtilities.TraceWarning("{0} changed on disk, but has no actual content change.", _fileBeingWatched); } } catch (OperationCanceledException) { // Project is already unloaded } }