| File: MS\Internal\Data\AsyncDataRequest.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Description: Defines a request to the async data system. // // Specs: Asynchronous Data Model.mht // namespace MS.Internal.Data { /// <summary> Type for the work and completion delegates of an AsyncDataRequest </summary> internal delegate object AsyncRequestCallback(AsyncDataRequest request); /// <summary> Status of an async data request. </summary> internal enum AsyncRequestStatus { /// <summary> Request has not been started </summary> Waiting, /// <summary> Request is in progress </summary> Working, /// <summary> Request has been completed </summary> Completed, /// <summary> Request was cancelled </summary> Cancelled, /// <summary> Request failed </summary> Failed } /// <summary> A request to the async data system. </summary> internal class AsyncDataRequest { //------------------------------------------------------ // // Constructors // //------------------------------------------------------ /// <summary> Constructor </summary> internal AsyncDataRequest(object bindingState, AsyncRequestCallback workCallback, AsyncRequestCallback completedCallback, params object[] args ) { _bindingState = bindingState; _workCallback = workCallback; _completedCallback = completedCallback; _args = args; } //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ /* unused by default scheduler. Restore for custom schedulers. /// <summary> The "user data" from the binding that issued the request. </summary> public object BindingState { get { return _bindingState; } } */ /// <summary> The result of the request (valid when request is completed). </summary> public object Result { get { return _result; } } /// <summary> The status of the request. </summary> public AsyncRequestStatus Status { get { return _status; } } /// <summary> The exception (for a failed request). </summary> public Exception Exception { get { return _exception; } } //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ /// <summary> Run the request's work delegate and return the result. </summary> /// <remarks> /// This method should be called synchronously on a worker thread, as it /// calls the work delegate, which potentially takes a long time. The /// method sets the status to "Working". It is normally followed by a /// call to Complete. /// /// If the request has already been run or has been abandoned, this method /// returns null. /// </remarks> public object DoWork() { if (DoBeginWork() && _workCallback != null) return _workCallback(this); else return null; } /// <summary>If the request is in the "Waiting" state, return true and /// set its status to "Working". Otherwise return false. /// </summary> /// <remarks> /// This method is thread-safe and works atomically. Therefore only /// one thread will be permitted to run the request. /// </remarks> public bool DoBeginWork() { return ChangeStatus(AsyncRequestStatus.Working); } /// <summary> Set the request's status to "Completed", save the result, /// and call the completed delegate. </summary> /// <remarks> /// This method should be called on any thread, after /// either calling DoWork or performing the work for a request in some /// other way. /// /// If the request has already been run or has been abandoned, this method /// does nothing. /// </remarks> public void Complete(object result) { if (ChangeStatus(AsyncRequestStatus.Completed)) { _result = result; if (_completedCallback != null) _completedCallback(this); } } /// <summary> Cancel the request.</summary> /// <remarks> This method can be called from any thread. /// <p>Calling Cancel does not actually terminate the work being /// done on behalf of the request, but merely causes the result /// of that work to be ignored.</p> /// </remarks> public void Cancel() { ChangeStatus(AsyncRequestStatus.Cancelled); } /// <summary> Fail the request because of an exception.</summary> /// <remarks> This method can be called from any thread. </remarks> public void Fail(Exception exception) { if (ChangeStatus(AsyncRequestStatus.Failed)) { _exception = exception; if (_completedCallback != null) _completedCallback(this); } } //------------------------------------------------------ // // Internal properties // //------------------------------------------------------ /// <summary> The caller-defined arguments. </summary> internal object[] Args { get { return _args; } } //------------------------------------------------------ // // Private methods // //------------------------------------------------------ // Change the status to the new status. Return true if this is allowed. // Do it all atomically. private bool ChangeStatus(AsyncRequestStatus newStatus) { bool allowChange = false; lock (SyncRoot) { switch (newStatus) { case AsyncRequestStatus.Working: allowChange = (_status == AsyncRequestStatus.Waiting); break; case AsyncRequestStatus.Completed: allowChange = (_status == AsyncRequestStatus.Working); break; case AsyncRequestStatus.Cancelled: allowChange = (_status == AsyncRequestStatus.Waiting) || (_status == AsyncRequestStatus.Working); break; case AsyncRequestStatus.Failed: allowChange = (_status == AsyncRequestStatus.Working); break; } if (allowChange) _status = newStatus; } return allowChange; } //------------------------------------------------------ // // Private data // //------------------------------------------------------ private AsyncRequestStatus _status; private object _result; private object _bindingState; private object[] _args; private Exception _exception; private AsyncRequestCallback _workCallback; private AsyncRequestCallback _completedCallback; private readonly object SyncRoot = new object(); // for synchronization } /// <summary> Async request to get the value of a property on an item. </summary> internal class AsyncGetValueRequest : AsyncDataRequest { //------------------------------------------------------ // // Constructors // //------------------------------------------------------ /// <summary> Constructor. </summary> internal AsyncGetValueRequest(object item, string propertyName, object bindingState, AsyncRequestCallback workCallback, AsyncRequestCallback completedCallback, params object[] args ) : base(bindingState, workCallback, completedCallback, args) { _item = item; _propertyName = propertyName; } //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ /// <summary> The item whose property is being requested </summary> public object SourceItem { get { return _item; } } /* unused by default scheduler. Restore for custom schedulers. /// <summary> The name of the property being requested </summary> public string PropertyName { get { return _propertyName; } } */ //------------------------------------------------------ // // Private data // //------------------------------------------------------ private object _item; private string _propertyName; } /// <summary> Async request to set the value of a property on an item. </summary> internal class AsyncSetValueRequest : AsyncDataRequest { //------------------------------------------------------ // // Constructors // //------------------------------------------------------ /// <summary> Constructor. </summary> internal AsyncSetValueRequest(object item, string propertyName, object value, object bindingState, AsyncRequestCallback workCallback, AsyncRequestCallback completedCallback, params object[] args ) : base(bindingState, workCallback, completedCallback, args) { _item = item; _propertyName = propertyName; _value = value; } //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ /// <summary> The item whose property is being set </summary> public object TargetItem { get { return _item; } } /* unused by default scheduler. Restore for custom schedulers. /// <summary> The name of the property being set </summary> public string PropertyName { get { return _propertyName; } } */ /// <summary> The new value for the property </summary> public object Value { get { return _value; } } //------------------------------------------------------ // // Private data // //------------------------------------------------------ private object _item; private string _propertyName; private object _value; } }