150 lines · 6.0 KB · C#
RawDownload
//******************************************************************************************************//  TaskSynchronizedOperation.cs - Gbtc////  Copyright © 2021, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  02/26/2021 - Stephen C. Wills//       Generated original version of source code.////****************************************************************************************************** using System;using System.Threading.Tasks; namespace GSF.Threading{    /// <summary>    /// Represents a task-based synchronized operation    /// that cannot run while it is already in progress.    /// </summary>    /// <remarks>    /// The action performed by the <see cref="TaskSynchronizedOperation"/> is executed using    /// <see cref="Task.Run(Func{Task})"/>. Pending actions run when the task returned by the    /// asynchronous action is completed. This synchronized operation only supports the async    /// versions of the <see cref="ISynchronizedOperation"/> interface because the async action    /// cannot be executed synchronously.    /// </remarks>    public class TaskSynchronizedOperation : ISynchronizedOperation    {        #region [ Members ]         // Nested Types        private class SynchronizedOperation : SynchronizedOperationBase        {            private Func<Task> AsyncAction { get; }            private Action<Exception> ExceptionHandler { get; }             public SynchronizedOperation(Func<Task> asyncAction, Action<Exception> exceptionHandler)                : base(() => { })            {                if (asyncAction is null)                    throw new ArgumentNullException(nameof(asyncAction));                 AsyncAction = asyncAction;                ExceptionHandler = exceptionHandler;            }             protected override void ExecuteActionAsync()            {                _ = Task.Run(async () =>                {                    try { await AsyncAction(); }                    catch (Exception ex) { TryHandleException(ex); }                     if (ExecuteAction())                        ExecuteActionAsync();                });            }             private void TryHandleException(Exception ex)            {                try { ExceptionHandler?.Invoke(ex); }                catch { /* No other way to handle exceptions at this point */ }            }        }         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new instance of the <see cref="TaskSynchronizedOperation"/> class.        /// </summary>        /// <param name="asyncAction">The action to be performed during this operation.</param>        public TaskSynchronizedOperation(Func<Task> asyncAction)            : this(asyncAction, null)        {        }         /// <summary>        /// Creates a new instance of the <see cref="TaskSynchronizedOperation"/> class.        /// </summary>        /// <param name="asyncAction">The action to be performed during this operation.</param>        /// <param name="exceptionAction">The action to be performed if an exception is thrown from the action.</param>        public TaskSynchronizedOperation(Func<Task> asyncAction, Action<Exception> exceptionAction) =>            InternalSynchronizedOperation = new SynchronizedOperation(asyncAction, exceptionAction);         #endregion         #region [ Properties ]         /// <summary>        /// Gets a value to indicate whether the synchronized        /// operation is currently executing its action.        /// </summary>        public bool IsRunning => InternalSynchronizedOperation.IsRunning;         /// <summary>        /// Gets a value to indiate whether the synchronized operation        /// has an additional operation that is pending execution after        /// the currently running action has completed.        /// </summary>        public bool IsPending => InternalSynchronizedOperation.IsPending;         private SynchronizedOperation InternalSynchronizedOperation { get; }         #endregion         #region [ Methods ]         /// <summary>        /// Executes the action on another thread or marks the        /// operation as pending if the operation is already running.        /// </summary>        /// <remarks>        /// When the operation is marked as pending, it will run again after the        /// operation that is currently running has completed. This is useful if        /// an update has invalidated the operation that is currently running and        /// will therefore need to be run again.        /// </remarks>        public void RunOnceAsync() =>            InternalSynchronizedOperation.RunOnceAsync();         /// <summary>        /// Attempts to execute the action on another thread.        /// Does nothing if the operation is already running.        /// </summary>        public void TryRunOnceAsync() =>            InternalSynchronizedOperation.TryRunOnceAsync();         void ISynchronizedOperation.Run() => RunOnceAsync();        void ISynchronizedOperation.TryRun() => TryRunOnceAsync();        void ISynchronizedOperation.RunOnce() => RunOnceAsync();        void ISynchronizedOperation.TryRunOnce() => TryRunOnceAsync();         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t