Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Base / System / Windows / Threading / DispatcherOperation.cs / 1 / DispatcherOperation.cs
using System;
using System.Security;
using System.Security.Permissions;
using System.Threading;
namespace System.Windows.Threading
{
///
/// DispatcherOperation represents a delegate that has been
/// posted to the Dispatcher queue.
///
public sealed class DispatcherOperation
{
///
/// Critical: This code calls into InvokeInSecurityContext which can be used to process input
/// TreatAsSafe: This is ok to expose since the operation itself is ok . But this will
/// `blow up if something untowards is done in the operation that violates trust boundaries
/// .Essentially although this lets you execute arbitrary code that code cannot be doing
/// any untrusted operation
///
[SecurityCritical,SecurityTreatAsSafe]
static DispatcherOperation()
{
_invokeInSecurityContext = new ContextCallback(InvokeInSecurityContext);
}
///
/// Critical: accesses _executionContext
///
[SecurityCritical]
internal DispatcherOperation(
Dispatcher dispatcher,
Delegate method,
DispatcherPriority priority, // NOTE: should be Priority
object args,
bool isSingleParameter)
{
_dispatcher = dispatcher;
_method = method;
_priority = priority;
_isSingleParameter = isSingleParameter;
_args = args;
_executionContext = ExecutionContext.Capture();
}
///
/// Internal constructor used to generate a Dispatcher operation
/// when the dispatcher has shut down
///
///
///
///
internal DispatcherOperation(
Dispatcher dispatcher,
Delegate method,
DispatcherPriority priority
)
{
_dispatcher = dispatcher;
_method = method;
_priority = priority;
_status = DispatcherOperationStatus.Aborted;
}
///
/// Returns the Dispatcher that this operation was posted to.
///
public Dispatcher Dispatcher
{
get
{
return _dispatcher;
}
}
///
/// Gets or sets the priority of this operation within the
/// Dispatcher queue.
///
public DispatcherPriority Priority // NOTE: should be Priority
{
get
{
return _priority;
}
set
{
Dispatcher.ValidatePriority(value, "value");
if(value != _priority && _dispatcher.SetPriority(this, value))
{
_priority = value;
}
}
}
///
/// The status of this operation.
///
public DispatcherOperationStatus Status
{
get
{
return _status;
}
}
///
/// Waits for this operation to complete.
///
///
/// The status of the operation. To obtain the return value
/// of the invoked delegate, use the the Result property.
///
public DispatcherOperationStatus Wait()
{
return Wait(TimeSpan.FromMilliseconds(-1));
}
///
/// Waits for this operation to complete.
///
///
/// The maximum amount of time to wait.
///
///
/// The status of the operation. To obtain the return value
/// of the invoked delegate, use the the Result property.
///
///
/// Critical: This code calls into PushFrame which has a link demand
/// PublicOk: The act of setting a timeline for an operation to complete is a safe one
///
[SecurityCritical]
public DispatcherOperationStatus Wait(TimeSpan timeout)
{
if((_status == DispatcherOperationStatus.Pending || _status == DispatcherOperationStatus.Executing) &&
timeout.TotalMilliseconds != 0)
{
if(_dispatcher.Thread == Thread.CurrentThread)
{
if(_status == DispatcherOperationStatus.Executing)
{
// We are the dispatching thread, and the current operation state is
// executing, which means that the operation is in the middle of
// executing (on this thread) and is trying to wait for the execution
// to complete. Unfortunately, the thread will now deadlock, so
// we throw an exception instead.
throw new InvalidOperationException(SR.Get(SRID.ThreadMayNotWaitOnOperationsAlreadyExecutingOnTheSameThread));
}
// We are the dispatching thread for this operation, so
// we can't block. We will push a frame instead.
DispatcherOperationFrame frame = new DispatcherOperationFrame(this, timeout);
Dispatcher.PushFrame(frame);
}
else
{
// We are some external thread, so we can just block. Of
// course this means that the Dispatcher (queue)for this
// thread (if any) is now blocked. The COM STA model
// suggests that we should pump certain messages so that
// back-communication can happen. Underneath us, the CLR
// will pump the STA apartment for us, and we will allow
// the UI thread for a context to call
// Invoke(Priority.Max, ...) without going through the
// blocked queue.
DispatcherOperationEvent wait = new DispatcherOperationEvent(this, timeout);
wait.WaitOne();
}
}
return _status;
}
///
/// Aborts this operation.
///
///
/// False if the operation could not be aborted (because the
/// operation was already in progress)
///
public bool Abort()
{
bool removed = false;
if (_dispatcher != null)
{
removed = _dispatcher.Abort(this);
if (removed)
{
// Raise the Aborted so anyone who is waiting will wake up.
if (Aborted != null)
{
Aborted(this, EventArgs.Empty);
}
}
}
return removed;
}
///
/// Name of this operation.
///
///
/// Returns a string representation of the operation to be invoked.
///
internal String Name
{
get
{
return _method.Method.DeclaringType + "." + _method.Method.Name;
}
}
///
/// Returns the result of the operation if it has completed.
///
public object Result
{
get
{
return _result;
}
}
///
/// An event that is raised when the operation is aborted.
///
public event EventHandler Aborted;
///
/// An event that is raised when the operation completes.
///
public event EventHandler Completed;
// Note: this is called by the Dispatcher to actually invoke the operation.
// Invoke --> InvokeInSecurityContext --> InvokeImpl
///
/// Critical: This code calls into ExecutionContext.Run which is link demand protected
/// accesses _executionContext
///
[SecurityCritical]
internal object Invoke()
{
// Mark this operation as executing.
_status = DispatcherOperationStatus.Executing;
// Continue using the execution context that was active when the operation
// was begun.
if(_executionContext != null)
{
ExecutionContext.Run(_executionContext, _invokeInSecurityContext, this);
}
else
{
// _executionContext can be null if someone called
// ExecutionContext.SupressFlow before calling BeginInvoke/Invoke.
// In this case we'll just call the invokation directly.
// SupressFlow is a privileged operation, so this is not a
// security hole.
_invokeInSecurityContext(this);
}
// Mark this operation as completed.
_status = DispatcherOperationStatus.Completed;
// Raise the Completed so anyone who is waiting will wake up.
if(Completed != null)
{
Completed(this, EventArgs.Empty);
}
return _result;
}
// Invoke --> InvokeInSecurityContext --> InvokeImpl
///
/// Critical: This code can execute arbitrary code
///
[SecurityCritical]
private static void InvokeInSecurityContext(Object state)
{
DispatcherOperation operation = (DispatcherOperation) state;
operation.InvokeImpl();
}
// Invoke --> InvokeInSecurityContext --> InvokeImpl
///
/// Critical: This code calls into SynchronizationContext.SetSynchronizationContext which link demands
///
[SecurityCritical]
private void InvokeImpl()
{
SynchronizationContext oldSynchronizationContext = SynchronizationContext.Current;
try
{
// We are executing under the "foreign" execution context, but the
// SynchronizationContext must be for the correct dispatcher.
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(_dispatcher));
// Invoke the delegate that does the work for this operation.
_result = _dispatcher.WrappedInvoke(_method, _args, _isSingleParameter);
}
finally
{
SynchronizationContext.SetSynchronizationContext(oldSynchronizationContext);
}
}
private class DispatcherOperationFrame : DispatcherFrame
{
// Note: we pass "exitWhenRequested=false" to the base
// DispatcherFrame construsctor because we do not want to exit
// this frame if the dispatcher is shutting down. This is
// because we may need to invoke operations during the shutdown process.
public DispatcherOperationFrame(DispatcherOperation op, TimeSpan timeout) : base(false)
{
_operation = op;
// We will exit this frame once the operation is completed or aborted.
_operation.Aborted += new EventHandler(OnCompletedOrAborted);
_operation.Completed += new EventHandler(OnCompletedOrAborted);
// We will exit the frame if the operation is not completed within
// the requested timeout.
if(timeout.TotalMilliseconds > 0)
{
_waitTimer = new Timer(new TimerCallback(OnTimeout),
null,
timeout,
TimeSpan.FromMilliseconds(-1));
}
// Some other thread could have aborted the operation while we were
// setting up the handlers. We check the state again and mark the
// frame as "should not continue" if this happened.
if(_operation._status != DispatcherOperationStatus.Pending)
{
Exit();
}
}
private void OnCompletedOrAborted(object sender, EventArgs e)
{
Exit();
}
private void OnTimeout(object arg)
{
Exit();
}
private void Exit()
{
Continue = false;
if(_waitTimer != null)
{
_waitTimer.Dispose();
}
_operation.Aborted -= new EventHandler(OnCompletedOrAborted);
_operation.Completed -= new EventHandler(OnCompletedOrAborted);
}
private DispatcherOperation _operation;
private Timer _waitTimer;
}
private class DispatcherOperationEvent
{
public DispatcherOperationEvent(DispatcherOperation op, TimeSpan timeout)
{
_operation = op;
_timeout = timeout;
_event = new ManualResetEvent(false);
_eventClosed = false;
lock(_instanceLock)
{
// We will set our event once the operation is completed or aborted.
_operation.Aborted += new EventHandler(OnCompletedOrAborted);
_operation.Completed += new EventHandler(OnCompletedOrAborted);
// Since some other thread is dispatching this operation, it could
// have been dispatched while we were setting up the handlers.
// We check the state again and set the event ourselves if this
// happened.
if(_operation._status != DispatcherOperationStatus.Pending && _operation._status != DispatcherOperationStatus.Executing)
{
_event.Set();
}
}
}
private void OnCompletedOrAborted(object sender, EventArgs e)
{
lock(_instanceLock)
{
if(!_eventClosed)
{
_event.Set();
}
}
}
public void WaitOne()
{
_event.WaitOne(_timeout, false);
lock(_instanceLock)
{
if(!_eventClosed)
{
// Cleanup the events.
_operation.Aborted -= new EventHandler(OnCompletedOrAborted);
_operation.Completed -= new EventHandler(OnCompletedOrAborted);
// Close the event immediately instead of waiting for a GC
// because the Dispatcher is a a high-activity component and
// we could run out of events.
_event.Close();
_eventClosed = true;
}
}
}
private DispatcherOperation _operation;
private TimeSpan _timeout;
private ManualResetEvent _event;
private bool _eventClosed;
private object _instanceLock = new object();
}
///
/// Obtained under an elevation.
///
[SecurityCritical]
private ExecutionContext _executionContext;
private static ContextCallback _invokeInSecurityContext;
private Dispatcher _dispatcher;
private DispatcherPriority _priority; // NOTE: should be Priority
private Delegate _method;
private object _args;
private bool _isSingleParameter;
internal DispatcherOperationStatus _status; // set from Dispatcher
private object _result;
internal PriorityItem _item; // The Dispatcher sets this when it enques/deques the item.
}
///
/// A convenient delegate to use for dispatcher operations.
///
public delegate object DispatcherOperationCallback(object arg);
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TreeNodeEventArgs.cs
- RuntimeCompatibilityAttribute.cs
- RichTextBox.cs
- Transform.cs
- PinnedBufferMemoryStream.cs
- WmfPlaceableFileHeader.cs
- _ChunkParse.cs
- HijriCalendar.cs
- URLIdentityPermission.cs
- XmlSchemaAttribute.cs
- XmlSchemaDatatype.cs
- WebPartTracker.cs
- BitConverter.cs
- SQLDateTimeStorage.cs
- RegexCompilationInfo.cs
- FormViewModeEventArgs.cs
- ThemeDictionaryExtension.cs
- HtmlEmptyTagControlBuilder.cs
- DataGridViewEditingControlShowingEventArgs.cs
- ModelFunction.cs
- ProfileGroupSettingsCollection.cs
- SerializerWriterEventHandlers.cs
- TextEditor.cs
- ServiceHttpModule.cs
- DelegateTypeInfo.cs
- PositiveTimeSpanValidatorAttribute.cs
- MsmqIntegrationValidationBehavior.cs
- Transactions.cs
- FontWeightConverter.cs
- Exceptions.cs
- DoubleAnimation.cs
- Pointer.cs
- JsonEncodingStreamWrapper.cs
- HostingPreferredMapPath.cs
- Debugger.cs
- FormViewRow.cs
- TypeConverter.cs
- SettingsPropertyCollection.cs
- SrgsText.cs
- GradientBrush.cs
- Certificate.cs
- AccessorTable.cs
- NativeWindow.cs
- TextParentUndoUnit.cs
- Base64Decoder.cs
- PerformanceCounterNameAttribute.cs
- BevelBitmapEffect.cs
- TextElement.cs
- AssemblyUtil.cs
- ComEventsHelper.cs
- CompiledQuery.cs
- sqlstateclientmanager.cs
- WsdlInspector.cs
- XdrBuilder.cs
- Translator.cs
- ControlCachePolicy.cs
- VisualTransition.cs
- AssemblyInfo.cs
- HwndKeyboardInputProvider.cs
- XmlQueryOutput.cs
- FixedFindEngine.cs
- InternalPolicyElement.cs
- OraclePermission.cs
- XamlTemplateSerializer.cs
- SizeAnimationUsingKeyFrames.cs
- AliasExpr.cs
- ConnectionStringsExpressionEditor.cs
- SafeProcessHandle.cs
- DbProviderSpecificTypePropertyAttribute.cs
- SevenBitStream.cs
- ToolStripItemCollection.cs
- FormattedText.cs
- StickyNoteContentControl.cs
- ListViewTableRow.cs
- ResourceIDHelper.cs
- QueryOperatorEnumerator.cs
- ImageInfo.cs
- BrowsableAttribute.cs
- documentsequencetextpointer.cs
- MsmqDiagnostics.cs
- RepeatBehavior.cs
- CookieProtection.cs
- ContainerParaClient.cs
- SqlClientFactory.cs
- ConfigurationElement.cs
- InstanceLockQueryResult.cs
- PriorityBinding.cs
- AssertFilter.cs
- JavaScriptString.cs
- DesignerProperties.cs
- Util.cs
- TTSEvent.cs
- DocumentSequenceHighlightLayer.cs
- AssemblyUtil.cs
- MeasurementDCInfo.cs
- UnionCodeGroup.cs
- OleDbMetaDataFactory.cs
- XmlAttributeAttribute.cs
- IERequestCache.cs
- XmlSchemaExternal.cs