Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Tracking / TrackingProvider.cs / 1305376 / TrackingProvider.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.Activities.Tracking { using System; using System.Activities; using System.Collections; using System.Collections.Generic; using System.Runtime; class TrackingProvider { ListtrackingParticipants; Dictionary profileSubscriptions; IList pendingTrackingRecords; Activity definition; bool filterValuesSetExplicitly; Hashtable activitySubscriptions; long nextTrackingRecordNumber; public TrackingProvider(Activity definition) { this.definition = definition; this.ShouldTrack = true; this.ShouldTrackActivityStateRecords = true; this.ShouldTrackActivityStateRecordsExecutingState = true; this.ShouldTrackActivityStateRecordsClosedState = true; this.ShouldTrackBookmarkResumptionRecords = true; this.ShouldTrackActivityScheduledRecords = true; this.ShouldTrackCancelRequestedRecords = true; this.ShouldTrackFaultPropagationRecords = true; this.ShouldTrackWorkflowInstanceRecords = true; } public bool HasPendingRecords { get { return (this.pendingTrackingRecords != null && this.pendingTrackingRecords.Count > 0) || !this.filterValuesSetExplicitly; } } public long NextTrackingRecordNumber { get { return this.nextTrackingRecordNumber; } } public bool ShouldTrack { get; private set; } public bool ShouldTrackWorkflowInstanceRecords { get; private set; } public bool ShouldTrackBookmarkResumptionRecords { get; private set; } public bool ShouldTrackActivityScheduledRecords { get; private set; } public bool ShouldTrackActivityStateRecords { get; private set; } public bool ShouldTrackActivityStateRecordsExecutingState { get; private set; } public bool ShouldTrackActivityStateRecordsClosedState { get; private set; } public bool ShouldTrackCancelRequestedRecords { get; private set; } public bool ShouldTrackFaultPropagationRecords { get; private set; } long GetNextRecordNumber() { // We blindly do this. On the off chance that a workflow causes it to loop back // around it shouldn't cause the workflow to fail and the tracking information // will still be salvagable. return this.nextTrackingRecordNumber++; } public void OnDeserialized(long nextTrackingRecordNumber) { this.nextTrackingRecordNumber = nextTrackingRecordNumber; } public void AddRecord(TrackingRecord record) { if (this.pendingTrackingRecords == null) { this.pendingTrackingRecords = new List (); } record.RecordNumber = GetNextRecordNumber(); this.pendingTrackingRecords.Add(record); } public void AddParticipant(TrackingParticipant participant) { if (this.trackingParticipants == null) { this.trackingParticipants = new List (); this.profileSubscriptions = new Dictionary (); } this.trackingParticipants.Add(participant); } public void FlushPendingRecords(TimeSpan timeout) { try { if (this.HasPendingRecords) { TimeoutHelper helper = new TimeoutHelper(timeout); for (int i = 0; i < this.trackingParticipants.Count; i++) { TrackingParticipant participant = this.trackingParticipants[i]; RuntimeTrackingProfile runtimeProfile = GetRuntimeTrackingProfile(participant); // HasPendingRecords can be true for the sole purpose of populating our initial profiles, so check again here if (this.pendingTrackingRecords != null) { for (int j = 0; j < this.pendingTrackingRecords.Count; j++) { TrackingRecord currentRecord = this.pendingTrackingRecords[j]; Fx.Assert(currentRecord != null, "We should never come across a null context."); TrackingRecord preparedRecord = null; bool shouldClone = this.trackingParticipants.Count > 1; if (runtimeProfile == null) { preparedRecord = shouldClone ? currentRecord.Clone() : currentRecord; } else { preparedRecord = runtimeProfile.Match(currentRecord, shouldClone); } if (preparedRecord != null) { participant.Track(preparedRecord, helper.RemainingTime()); if (TD.TrackingRecordRaisedIsEnabled()) { TD.TrackingRecordRaised(preparedRecord.ToString(), participant.GetType().ToString()); } } } } } } } finally { // Note that if we fail to track yet the workflow manages to recover // we will attempt to track those records again. ClearPendingRecords(); } } public IAsyncResult BeginFlushPendingRecords(TimeSpan timeout, AsyncCallback callback, object state) { return new FlushPendingRecordsAsyncResult(this, timeout, callback, state); } public void EndFlushPendingRecords(IAsyncResult result) { FlushPendingRecordsAsyncResult.End(result); } public bool ShouldTrackActivity(string name) { return this.activitySubscriptions == null || this.activitySubscriptions.ContainsKey(name) || this.activitySubscriptions.ContainsKey("*"); } void ClearPendingRecords() { if (this.pendingTrackingRecords != null) { //since the number of records is small, it is faster to remove from end than to call List.Clear for (int i = this.pendingTrackingRecords.Count - 1; i >= 0; i--) { this.pendingTrackingRecords.RemoveAt(i); } } } RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingParticipant participant) { TrackingProfile profile; RuntimeTrackingProfile runtimeProfile; if (!this.profileSubscriptions.TryGetValue(participant, out runtimeProfile)) { profile = participant.TrackingProfile; if (profile != null) { runtimeProfile = RuntimeTrackingProfile.GetRuntimeTrackingProfile(profile, this.definition); Merge(runtimeProfile.Filter); //Add the names to the list of activities that have subscriptions. This provides a quick lookup //for the runtime to check if a TrackingRecord has to be created. IEnumerable activityNames = runtimeProfile.GetSubscribedActivityNames(); if (activityNames != null) { if (this.activitySubscriptions == null) { this.activitySubscriptions = new Hashtable(); } foreach (string name in activityNames) { if (this.activitySubscriptions[name] == null) { this.activitySubscriptions[name] = name; } } } } else { //for null profiles, set all the filter flags. Merge(new TrackingRecordPreFilter(true)); } this.profileSubscriptions.Add(participant, runtimeProfile); } return runtimeProfile; } void Merge(TrackingRecordPreFilter filter) { if (!this.filterValuesSetExplicitly) { // This it the first filter we are merging this.filterValuesSetExplicitly = true; this.ShouldTrackActivityStateRecordsExecutingState = filter.TrackActivityStateRecordsExecutingState; this.ShouldTrackActivityScheduledRecords = filter.TrackActivityScheduledRecords; this.ShouldTrackActivityStateRecords = filter.TrackActivityStateRecords; this.ShouldTrackActivityStateRecordsClosedState = filter.TrackActivityStateRecordsClosedState; this.ShouldTrackBookmarkResumptionRecords = filter.TrackBookmarkResumptionRecords; this.ShouldTrackCancelRequestedRecords = filter.TrackCancelRequestedRecords; this.ShouldTrackFaultPropagationRecords = filter.TrackFaultPropagationRecords; this.ShouldTrackWorkflowInstanceRecords = filter.TrackWorkflowInstanceRecords; } else { this.ShouldTrackActivityStateRecordsExecutingState |= filter.TrackActivityStateRecordsExecutingState; this.ShouldTrackActivityScheduledRecords |= filter.TrackActivityScheduledRecords; this.ShouldTrackActivityStateRecords |= filter.TrackActivityStateRecords; this.ShouldTrackActivityStateRecordsClosedState |= filter.TrackActivityStateRecordsClosedState; this.ShouldTrackBookmarkResumptionRecords |= filter.TrackBookmarkResumptionRecords; this.ShouldTrackCancelRequestedRecords |= filter.TrackCancelRequestedRecords; this.ShouldTrackFaultPropagationRecords |= filter.TrackFaultPropagationRecords; this.ShouldTrackWorkflowInstanceRecords |= filter.TrackWorkflowInstanceRecords; } } class FlushPendingRecordsAsyncResult : AsyncResult { static AsyncCompletion trackingCompleteCallback = new AsyncCompletion(OnTrackingComplete); int currentRecord; int currentParticipant; TrackingProvider provider; TimeoutHelper timeoutHelper; public FlushPendingRecordsAsyncResult(TrackingProvider provider, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.provider = provider; this.timeoutHelper = new TimeoutHelper(timeout); if (RunLoop()) { Complete(true); } } bool RunLoop() { if (this.provider.HasPendingRecords) { while (this.currentParticipant < this.provider.trackingParticipants.Count) { TrackingParticipant participant = this.provider.trackingParticipants[this.currentParticipant]; RuntimeTrackingProfile runtimeProfile = this.provider.GetRuntimeTrackingProfile(participant); if (this.provider.pendingTrackingRecords != null) { while (this.currentRecord < this.provider.pendingTrackingRecords.Count) { bool completedSynchronously = PostTrackingRecord(participant, runtimeProfile); if (!completedSynchronously) { return false; } } } this.currentRecord = 0; this.currentParticipant++; } } // We've now tracked all of the records. this.provider.ClearPendingRecords(); return true; } static bool OnTrackingComplete(IAsyncResult result) { Fx.Assert(!result.CompletedSynchronously, "TrackingAsyncResult.OnTrackingComplete should not get called with a result that is CompletedSynchronously"); FlushPendingRecordsAsyncResult thisPtr = (FlushPendingRecordsAsyncResult)result.AsyncState; TrackingParticipant participant = thisPtr.provider.trackingParticipants[thisPtr.currentParticipant]; bool isSuccessful = false; try { participant.EndTrack(result); isSuccessful = true; } finally { if (!isSuccessful) { thisPtr.provider.ClearPendingRecords(); } } return thisPtr.RunLoop(); } bool PostTrackingRecord(TrackingParticipant participant, RuntimeTrackingProfile runtimeProfile) { TrackingRecord originalRecord = this.provider.pendingTrackingRecords[this.currentRecord]; this.currentRecord++; bool isSuccessful = false; try { TrackingRecord preparedRecord = null; bool shouldClone = this.provider.trackingParticipants.Count > 1; if (runtimeProfile == null) { preparedRecord = shouldClone ? originalRecord.Clone() : originalRecord; } else { preparedRecord = runtimeProfile.Match(originalRecord, shouldClone); } if (preparedRecord != null) { IAsyncResult result = participant.BeginTrack(preparedRecord, this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(trackingCompleteCallback), this); if (TD.TrackingRecordRaisedIsEnabled()) { TD.TrackingRecordRaised(preparedRecord.ToString(), participant.GetType().ToString()); } if (result.CompletedSynchronously) { participant.EndTrack(result); } else { isSuccessful = true; return false; } } isSuccessful = true; } finally { if (!isSuccessful) { this.provider.ClearPendingRecords(); } } return true; } public static void End(IAsyncResult result) { AsyncResult.End (result); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlSchemaAttribute.cs
- ConnectionPoolManager.cs
- AppDomain.cs
- DeviceContext.cs
- JournalEntryListConverter.cs
- IndentTextWriter.cs
- EqualityComparer.cs
- SqlConnectionHelper.cs
- RuntimeCompatibilityAttribute.cs
- IOThreadTimer.cs
- PeerNameResolver.cs
- ExtendedProtectionPolicy.cs
- PKCS1MaskGenerationMethod.cs
- TextContainerHelper.cs
- WindowsGraphics.cs
- XamlSerializerUtil.cs
- UserControlBuildProvider.cs
- Sentence.cs
- ObjectDisposedException.cs
- PatternMatcher.cs
- RequestCacheEntry.cs
- EasingKeyFrames.cs
- BinHexDecoder.cs
- AstTree.cs
- KeyGestureConverter.cs
- SeekableReadStream.cs
- VirtualPathProvider.cs
- WindowsScroll.cs
- FlowNode.cs
- MasterPageBuildProvider.cs
- DataListCommandEventArgs.cs
- Int32RectConverter.cs
- BindingExpressionUncommonField.cs
- HttpInputStream.cs
- SocketException.cs
- WebResourceAttribute.cs
- AssemblyNameProxy.cs
- ProcessHostConfigUtils.cs
- ExtentCqlBlock.cs
- TextWriterTraceListener.cs
- DbProviderServices.cs
- UInt16Converter.cs
- AssemblyHelper.cs
- ComponentManagerBroker.cs
- XslAst.cs
- FixedSOMTextRun.cs
- HostedHttpRequestAsyncResult.cs
- AnnotationElement.cs
- BindableAttribute.cs
- CommandEventArgs.cs
- ProcessModule.cs
- PropertyDescriptorCollection.cs
- ConfigurationElementProperty.cs
- DSACryptoServiceProvider.cs
- LocatorGroup.cs
- HandleCollector.cs
- Misc.cs
- FillRuleValidation.cs
- PropertyToken.cs
- AppDomainAttributes.cs
- ObjectDisposedException.cs
- BookmarkEventArgs.cs
- DataGridViewCellLinkedList.cs
- CapabilitiesUse.cs
- BatchStream.cs
- DataControlImageButton.cs
- GenericAuthenticationEventArgs.cs
- UniqueSet.cs
- Highlights.cs
- AnchoredBlock.cs
- _emptywebproxy.cs
- XamlSerializationHelper.cs
- WebPartCancelEventArgs.cs
- Types.cs
- MenuItemStyleCollection.cs
- Misc.cs
- FixedTextView.cs
- BitmapMetadataBlob.cs
- _FtpControlStream.cs
- BrowserInteropHelper.cs
- RowUpdatingEventArgs.cs
- StrokeNodeOperations2.cs
- BamlWriter.cs
- SessionPageStatePersister.cs
- LocalizationComments.cs
- OleAutBinder.cs
- TypeInitializationException.cs
- AtomContentProperty.cs
- XmlCompatibilityReader.cs
- HtmlTable.cs
- PlanCompiler.cs
- WinEventHandler.cs
- FacetDescription.cs
- StandardOleMarshalObject.cs
- HTMLTextWriter.cs
- MyContact.cs
- DataServiceExpressionVisitor.cs
- LOSFormatter.cs
- RbTree.cs
- TdsParserSessionPool.cs