@@ -156,66 +156,65 @@ public void ChainDisposal(IDisposable disposable)
156156    /// both evaluation and build updates may arrive in any order, so long as values 
157157    /// of each type are ordered correctly. 
158158    /// </para> 
159-     /// <para> 
160-     /// Calls must not overlap. This method is not thread-safe. This method is designed 
161-     /// to be called from a dataflow ActionBlock, which will serialize calls, so we 
162-     /// needn't perform any locking or protection here. 
163-     /// </para> 
164159    /// </remarks> 
165160    /// <param name="update">The project update to integrate.</param> 
166161    /// <returns>A task that completes when the update has been integrated.</returns> 
167-     internal  async   Task  OnWorkspaceUpdateAsync ( IProjectVersionedValue < WorkspaceUpdate >  update ) 
162+     internal  Task  OnWorkspaceUpdateAsync ( IProjectVersionedValue < WorkspaceUpdate >  update ) 
168163    { 
169-         Verify . NotDisposed ( this ) ; 
164+         // Prevent disposal during the update. 
165+         return  ExecuteUnderLockAsync ( async  token => 
166+         { 
167+             Verify . NotDisposed ( this ) ; 
168+ 
169+             await  InitializeAsync ( _unloadCancellationToken ) ; 
170170
171-         await   InitializeAsync ( _unloadCancellationToken ) ; 
171+              Assumes . True ( _state   is   WorkspaceState . Uninitialized  or  WorkspaceState . Initialized ) ; 
172172
173-         Assumes . True ( _state  is  WorkspaceState . Uninitialized  or WorkspaceState . Initialized ) ; 
173+             await  _joinableTaskFactory . RunAsync ( ApplyUpdateWithinLockAsync ) ; 
174+         } ) ; 
174175
175-         await  _joinableTaskFactory . RunAsync ( 
176-             async  ( )  => 
176+         async  Task  ApplyUpdateWithinLockAsync ( ) 
177+         { 
178+             // We will always receive an evaluation update before the first build update. 
179+ 
180+             if  ( TryTransition ( WorkspaceState . Uninitialized ,  WorkspaceState . Initialized ) ) 
177181            { 
178-                 // Calls never overlap. No synchronisation is needed here.  
179-                 // We can receive either evaluation OR build data  first. 
182+                 // Note that we create operation progress registrations using the first primary (active) configuration  
183+                 // within the slice. Over time this may change, but we keep the same registration to the  first seen . 
180184
181-                 if   ( TryTransition ( WorkspaceState . Uninitialized ,   WorkspaceState . Initialized ) ) 
185+                 ConfiguredProject   configuredProject   =   update . Value   switch 
182186                { 
183-                     // Note that we create operation progress registrations using the first primary (active) configuration 
184-                     // within the slice. Over time this may change, but we keep the same registration to the first seen. 
185- 
186-                     ConfiguredProject  configuredProject  =  update . Value  switch 
187-                     { 
188-                         {  EvaluationUpdate :  EvaluationUpdate  update  }  =>  update . ConfiguredProject , 
189-                         {  BuildUpdate :  BuildUpdate  update  }  =>  update . ConfiguredProject , 
190-                         _ =>  throw  Assumes . NotReachable ( ) 
191-                     } ; 
187+                     {  EvaluationUpdate :  EvaluationUpdate  update  }  =>  update . ConfiguredProject , 
188+                     {  BuildUpdate :  BuildUpdate  update  }  =>  update . ConfiguredProject , 
189+                     _ =>  throw  Assumes . NotReachable ( ) 
190+                 } ; 
192191
193-                      _evaluationProgressRegistration  =  _dataProgressTrackerService . RegisterForIntelliSense ( this ,  configuredProject ,  "LanguageServiceHost.Workspace.Evaluation" ) ; 
194-                      _buildProgressRegistration  =  _dataProgressTrackerService . RegisterForIntelliSense ( this ,  configuredProject ,  "LanguageServiceHost.Workspace.ProjectBuild" ) ; 
192+                 _evaluationProgressRegistration  =  _dataProgressTrackerService . RegisterForIntelliSense ( this ,  configuredProject ,  "LanguageServiceHost.Workspace.Evaluation" ) ; 
193+                 _buildProgressRegistration  =  _dataProgressTrackerService . RegisterForIntelliSense ( this ,  configuredProject ,  "LanguageServiceHost.Workspace.ProjectBuild" ) ; 
195194
196-                      _disposableBag . Add ( _evaluationProgressRegistration ) ; 
197-                      _disposableBag . Add ( _buildProgressRegistration ) ; 
198-                  } 
195+                 _disposableBag . Add ( _evaluationProgressRegistration ) ; 
196+                 _disposableBag . Add ( _buildProgressRegistration ) ; 
197+             } 
199198
200-                 try 
201-                 { 
202-                     await  ( update . Value  switch 
203-                     { 
204-                         {  EvaluationUpdate :  not null  }  =>  OnEvaluationUpdateAsync ( update . Derive ( u =>  u . EvaluationUpdate ! ) ) , 
205-                         {  BuildUpdate :  not null  }  =>  OnBuildUpdateAsync ( update . Derive ( u =>  u . BuildUpdate ! ) ) , 
206-                         _ =>  throw  Assumes . NotReachable ( ) 
207-                     } ) ; 
208-                 } 
209-                 catch 
199+             try 
200+             { 
201+                 await  ( update . Value  switch 
210202                { 
211-                     // Tear down on any exception 
212-                     await  DisposeAsync ( ) ; 
203+                     {  EvaluationUpdate :  not null  }  =>  OnEvaluationUpdateAsync ( update . Derive ( u =>  u . EvaluationUpdate ! ) ) , 
204+                     {  BuildUpdate :  not null  }  =>  OnBuildUpdateAsync ( update . Derive ( u =>  u . BuildUpdate ! ) ) , 
205+                     _ =>  throw  Assumes . NotReachable ( ) 
206+                 } ) ; 
207+             } 
208+             catch 
209+             { 
210+                 // Tear down on any exception 
211+                 await  DisposeAsync ( ) ; 
213212
214-                      // Exceptions here are product errors, so let the exception escape in order 
215-                      // to produce an upstream NFE. 
216-                      throw ; 
217-                  } 
218-              } ) ; 
213+                 // Exceptions here are product errors, so let the exception escape in order 
214+                 // to produce an upstream NFE. 
215+                 throw ; 
216+             } 
217+         } 
219218    } 
220219
221220    private  async  Task  OnEvaluationUpdateAsync ( IProjectVersionedValue < EvaluationUpdate >  evaluationUpdate ) 
0 commit comments