/// <summary> /// Initialize the watcher. /// </summary> protected override async Task InitializeCoreAsync(CancellationToken cancellationToken) { _fileChangeService = (IVsFileChangeEx)(await _asyncServiceProvider.GetServiceAsync(typeof(SVsFileChangeEx)).ConfigureAwait(false)); // Explicitly get back to the thread pool for the rest of this method so we don't tie up the UI thread; await TaskScheduler.Default; await _projectTasksService.LoadedProjectAsync(() => { // The tree source to get changes to the tree so that we can identify when the assets file changes. var treeSource = _fileSystemTreeProvider.Tree.SyncLinkOptions(); // The property source used to get the value of the $ProjectAssetsFile property so that we can identify the location of the assets file. var sourceLinkOptions = new StandardRuleDataflowLinkOptions { RuleNames = Empty.OrdinalIgnoreCaseStringSet.Add(ConfigurationGeneral.SchemaName), PropagateCompletion = true }; var propertySource = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(sourceLinkOptions); var target = new ActionBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(DataFlow_ChangedAsync); // Join the two sources so that we get synchronized versions of the data. _treeWatcher = ProjectDataSources.SyncLinkTo(treeSource, propertySource, target); return(Task.CompletedTask); }).ConfigureAwait(false); }
protected override void Initialize() { // Create our broadcast block for subscribers to get new ILaunchProfiles Information _broadcastBlock = DataflowBlockSlim.CreateBroadcastBlock <ILaunchSettings>(); _changedSourceBlock = _broadcastBlock.SafePublicize(); // Subscribe to changes to the broadcast block using the idle scheduler. This should filter out a lot of the intermediates // states that files can be in. if (_projectSubscriptionService != null) { // The use of AsyncLazy with dataflow can allow state stored in the execution context to leak through. The downstream affect is // calls to say, get properties, may fail. To avoid this, we capture the execution context here, and it will be reapplied when // we get new subscription data from the dataflow. ITargetBlock <IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCapabilitiesSnapshot> > > projectChangesBlock = DataflowBlockSlim.CreateActionBlock( DataflowUtilities.CaptureAndApplyExecutionContext <IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCapabilitiesSnapshot> > >(ProjectRuleBlock_ChangedAsync)); StandardRuleDataflowLinkOptions evaluationLinkOptions = DataflowOption.WithRuleNames(ProjectDebugger.SchemaName); _projectRuleSubscriptionLink = ProjectDataSources.SyncLinkTo( _projectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(evaluationLinkOptions), _commonProjectServices.Project.Capabilities.SourceBlock.SyncLinkOptions(), projectChangesBlock, linkOptions: DataflowOption.PropagateCompletion); } // Make sure we are watching the file at this point WatchLaunchSettingsFile(); }
private async Task ResetSubscriptions() { // active configuration should be updated before resetting subscriptions await RefreshActiveConfigurationAsync().ConfigureAwait(false); _designTimeBuildSubscriptionLink?.Dispose(); var currentProjects = await _activeConfiguredProjectsProvider.GetActiveConfiguredProjectsAsync() .ConfigureAwait(false); if (currentProjects != null) { var sourceLinkOptions = new StandardRuleDataflowLinkOptions { RuleNames = _designTimeBuildWatchedRules, PropagateCompletion = true }; var sourceBlocks = currentProjects.Objects.Select( cp => cp.Services.ProjectSubscription.JointRuleSource.SourceBlock.SyncLinkOptions <IProjectValueVersions>(sourceLinkOptions)); var target = new ActionBlock <Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> >(ProjectPropertyChangedAsync); var targetLinkOptions = new DataflowLinkOptions { PropagateCompletion = true }; _designTimeBuildSubscriptionLink = ProjectDataSources.SyncLinkTo(sourceBlocks.ToImmutableList(), target, targetLinkOptions); } }
private async Task ResetSubscriptions() { _evaluationSubscriptionLink?.Dispose(); var currentProjects = await _activeConfiguredProjectsProvider.GetActiveConfiguredProjectsAsync().ConfigureAwait(false); if (currentProjects.Any()) { var sourceLinkOptions = new StandardRuleDataflowLinkOptions { RuleNames = _evaluationWatchedRules, PropagateCompletion = true }; var sourceBlocks = currentProjects.Select( cp => cp.Services.ProjectSubscription.ProjectRuleSource.SourceBlock.SyncLinkOptions <IProjectValueVersions>(sourceLinkOptions)); var target = new ActionBlock <Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> >(ProjectPropertyChangedAsync); var targetLinkOptions = new DataflowLinkOptions { PropagateCompletion = true }; _evaluationSubscriptionLink = ProjectDataSources.SyncLinkTo(sourceBlocks.ToImmutableList(), target, targetLinkOptions); } }
private void OnActiveConfigurationsChanged(IProjectVersionedValue <IConfigurationGroup <ConfiguredProject> > e) { if (IsDisposing || IsDisposed) { return; } // Clean up past subscriptions _designTimeBuildSubscriptionLink?.Dispose(); if (e.Value.Count > 0) { var sourceLinkOptions = new StandardRuleDataflowLinkOptions { RuleNames = s_designTimeBuildWatchedRules, PropagateCompletion = true }; var disposableBag = new DisposableBag(CancellationToken.None); // We are taking source blocks from multiple configured projects and creating a SyncLink to combine the sources. // The SyncLink will only publish data when the versions of the sources match. There is a problem with that. // The sources have some version components that will make this impossible to match across TFMs. We introduce a // intermediate block here that will remove those version components so that the synclink can actually sync versions. IEnumerable <ProjectDataSources.SourceBlockAndLink <IProjectValueVersions> > sourceBlocks = e.Value.Select( cp => { IReceivableSourceBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> > sourceBlock = cp.Services.ProjectSubscription.JointRuleSource.SourceBlock; IPropagatorBlock <IProjectVersionedValue <IProjectSubscriptionUpdate>, IProjectVersionedValue <IProjectSubscriptionUpdate> > versionDropper = CreateVersionDropperBlock(); disposableBag.AddDisposable(sourceBlock.LinkTo(versionDropper, sourceLinkOptions)); return(versionDropper.SyncLinkOptions <IProjectValueVersions>(sourceLinkOptions)); }); Action <Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> > action = ProjectPropertyChanged; var target = new ActionBlock <Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> >(action); var targetLinkOptions = new DataflowLinkOptions { PropagateCompletion = true }; ImmutableList <ProjectDataSources.SourceBlockAndLink <IProjectValueVersions> > sourceBlocksAndCapabilitiesOptions = sourceBlocks.ToImmutableList() .Insert(0, _projectVsServices.Project.Capabilities.SourceBlock.SyncLinkOptions <IProjectValueVersions>()); disposableBag.AddDisposable(ProjectDataSources.SyncLinkTo(sourceBlocksAndCapabilitiesOptions, target, targetLinkOptions)); _designTimeBuildSubscriptionLink = disposableBag; } }
private async Task ResetSubscriptionsAsync() { // active configuration should be updated before resetting subscriptions await RefreshActiveConfigurationAsync().ConfigureAwait(false); _designTimeBuildSubscriptionLink?.Dispose(); var currentProjects = await _activeConfiguredProjectsProvider.GetActiveConfiguredProjectsAsync() .ConfigureAwait(false); if (currentProjects != null) { var sourceLinkOptions = new StandardRuleDataflowLinkOptions { RuleNames = s_designTimeBuildWatchedRules, PropagateCompletion = true }; var disposableBag = new DisposableBag(CancellationToken.None); // We are taking source blocks from multiple configured projects and creating a SyncLink to combine the sources. // The SyncLink will only publish data when the versions of the sources match. There is a problem with that. // The sources have some version components that will make this impossible to match across TFMs. We introduce a // intermediate block here that will remove those version components so that the synclink can actually sync versions. var sourceBlocks = currentProjects.Objects.Select( cp => { var sourceBlock = cp.Services.ProjectSubscription.JointRuleSource.SourceBlock; var versionDropper = CreateVersionDropperBlock(); disposableBag.AddDisposable(sourceBlock.LinkTo(versionDropper, sourceLinkOptions)); return(versionDropper.SyncLinkOptions <IProjectValueVersions>(sourceLinkOptions)); }); var target = new ActionBlock <Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> >(ProjectPropertyChangedAsync); var targetLinkOptions = new DataflowLinkOptions { PropagateCompletion = true }; disposableBag.AddDisposable(ProjectDataSources.SyncLinkTo(sourceBlocks.ToImmutableList(), target, targetLinkOptions)); _designTimeBuildSubscriptionLink = disposableBag; } }
/// <summary> /// Initialize the watcher. /// </summary> protected override Task InitializeCoreAsync(CancellationToken cancellationToken) { return(_projectTasksService.LoadedProjectAsync(() => { // The tree source to get changes to the tree so that we can identify when the assets file changes. ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectTreeSnapshot> > treeSource = _fileSystemTreeProvider.Tree.SyncLinkOptions(); // The property source used to get the value of the $ProjectAssetsFile property so that we can identify the location of the assets file. StandardRuleDataflowLinkOptions sourceLinkOptions = DataflowOption.WithRuleNames(ConfigurationGeneral.SchemaName); ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectSubscriptionUpdate> > propertySource = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(sourceLinkOptions); ITargetBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > > target = DataflowBlockSlim.CreateActionBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(DataFlow_ChangedAsync); // Join the two sources so that we get synchronized versions of the data. _treeWatcher = ProjectDataSources.SyncLinkTo(treeSource, propertySource, target); return Task.CompletedTask; })); }
/// <summary> /// Initialize the watcher. /// </summary> protected override void Initialize() { _fileChangeService = _serviceProvider.GetService <IVsFileChangeEx, SVsFileChangeEx>(); // The tree source to get changes to the tree so that we can identify when the assets file changes. var treeSource = _fileSystemTreeProvider.Tree.SyncLinkOptions(); // The property source used to get the value of the $ProjectAssetsFile property so that we can identify the location of the assets file. var sourceLinkOptions = new StandardRuleDataflowLinkOptions { RuleNames = Empty.OrdinalIgnoreCaseStringSet.Add(ConfigurationGeneral.SchemaName), PropagateCompletion = true }; var propertySource = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(sourceLinkOptions); var target = new ActionBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(new Action <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(DataFlow_Changed)); // Join the two sources so that we get synchronized versions of the data. _treeWatcher = ProjectDataSources.SyncLinkTo(treeSource, propertySource, target); }
/// <summary> /// Initialize the watcher. /// </summary> protected override async Task InitializeCoreAsync(CancellationToken cancellationToken) { // Explicitly get back to the thread pool for the rest of this method so we don't tie up the UI thread; await TaskScheduler.Default; await _projectTasksService.LoadedProjectAsync(() => { // The tree source to get changes to the tree so that we can identify when the assets file changes. ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectTreeSnapshot> > treeSource = _fileSystemTreeProvider.Tree.SyncLinkOptions(); // The property source used to get the value of the $ProjectAssetsFile property so that we can identify the location of the assets file. StandardRuleDataflowLinkOptions sourceLinkOptions = DataflowOption.WithRuleNames(ConfigurationGeneral.SchemaName); ProjectDataSources.SourceBlockAndLink <IProjectVersionedValue <IProjectSubscriptionUpdate> > propertySource = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(sourceLinkOptions); var target = new ActionBlock <IProjectVersionedValue <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > >(DataFlow_ChangedAsync); // Join the two sources so that we get synchronized versions of the data. _treeWatcher = ProjectDataSources.SyncLinkTo(treeSource, propertySource, target); return(Task.CompletedTask); }); }