@@ -181,17 +181,26 @@ private void Init()
181181
182182 /// <summary>
183183 /// A snapshot of the device model received from the most recent Probe response,
184- /// keyed by device UUID. The dictionary is empty until the first probe succeeds,
185- /// and is replaced on every subsequent probe. Each <see cref="IDevice"/>'s
186- /// DataItems carry the fully wired <see cref="IDataItem.Container"/> and
187- /// <see cref="IDataItem.Device"/> back-pointers set during parsing, so consumers
188- /// can walk the component ancestry of any DataItem without re-parsing the
189- /// document.
184+ /// keyed by device UUID. The dictionary is empty until the first probe succeeds.
185+ /// Each call returns a fresh snapshot reflecting the most recently completed probe;
186+ /// previously returned snapshots are unaffected by subsequent probes. Each
187+ /// <see cref="IDevice"/>'s DataItems carry the fully wired
188+ /// <see cref="IDataItem.Container"/> and <see cref="IDataItem.Device"/>
189+ /// back-pointers set during parsing, so consumers can walk the component ancestry
190+ /// of any DataItem without re-parsing the document.
190191 /// </summary>
191192 /// <remarks>
192- /// The accessor returns an independent copy under the client's internal lock,
193- /// so callers may enumerate the snapshot without synchronising against the
194- /// worker thread that processes subsequent probes.
193+ /// <para>
194+ /// The dictionary returned by each call is a fresh allocation independent of the
195+ /// cache; the <see cref="IDevice"/> values within are shared references to cached
196+ /// instances that the client replaces wholesale on each probe. The accessor
197+ /// acquires the client's internal lock, so callers may enumerate the snapshot
198+ /// without synchronizing against the worker thread that processes subsequent probes.
199+ /// </para>
200+ /// <para>
201+ /// Each access allocates a fresh dictionary. Cache the returned reference if you
202+ /// read repeatedly between probes.
203+ /// </para>
195204 /// </remarks>
196205 public IReadOnlyDictionary < string , IDevice > Devices
197206 {
@@ -214,6 +223,11 @@ public IReadOnlyDictionary<string, IDevice> Devices
214223 /// its DataItems' <see cref="IDataItem.Container"/> and <see cref="IDataItem.Device"/>
215224 /// back-pointers set, and the agent's <c>InstanceId</c> stamped on each DataItem.
216225 /// </summary>
226+ /// <remarks>
227+ /// Handlers fire in document order while the cache is still being populated.
228+ /// Subscribe to <see cref="ProbeReceived"/> to receive notification after the full
229+ /// probe response has been processed.
230+ /// </remarks>
217231 public event EventHandler < IDevice > DeviceReceived ;
218232
219233 /// <summary>
@@ -875,11 +889,7 @@ private void ProcessProbeDocument(IDevicesResponseDocument document)
875889 _devices . Add ( outputDevice . Uuid , outputDevice ) ;
876890 }
877891
878- // Raise DeviceReceived for each parsed device. The event was
879- // previously raised against a separate list that was never
880- // populated, so it did not fire in the field; folding the
881- // invocation into the populate loop keeps the cache and the
882- // event in lockstep.
892+ // Fire per-device inside the populate loop so the cache and event stay in lockstep.
883893 DeviceReceived ? . Invoke ( this , outputDevice ) ;
884894 }
885895
@@ -1122,6 +1132,7 @@ private IComponentStream ProcessComponentStream(IMTConnectStreamsHeader header,
11221132 outputComponentStream . NativeName = inputComponentStream . NativeName ;
11231133 outputComponentStream . Uuid = inputComponentStream . Uuid ;
11241134
1135+ // Fully-qualified to disambiguate from the Devices property below; the namespace using above is shadowed inside this class.
11251136 if ( inputComponentStream . ComponentType == Agent . TypeId || inputComponentStream . ComponentType == MTConnect . Devices . Device . TypeId )
11261137 {
11271138 outputComponentStream . Component = GetCachedDevice ( deviceUuid ) ;
@@ -1178,6 +1189,7 @@ private async void CheckAssetChanged(IEnumerable<IObservation> observations, Can
11781189 {
11791190 if ( observations != null && observations . Count ( ) > 0 )
11801191 {
1192+ // Fully-qualified to disambiguate from the Devices property below; the namespace using above is shadowed inside this class.
11811193 var assetsChanged = observations . Where ( o => o . Type . ToUnderscoreUpper ( ) == MTConnect . Devices . DataItems . AssetChangedDataItem . TypeId ) ;
11821194 if ( assetsChanged != null )
11831195 {
0 commit comments