/// <summary> /// Executes an action once on the current thread. /// </summary> /// <param name="action"><see cref="Action"/> to run on current thread.</param> /// <remarks> /// This method provides exception handling for the action passed into this /// method with a couple of guarantees. The first is that regardless of what /// thread is executing the action passed into this method, the exception /// will be raised on the thread that the logical operation runs on. The /// second is that the RunIfPending method will be called if an exception /// does occur in the given action. /// </remarks> public void ExecuteAction(Action action) { try { action(); if (m_autoRunIfPending) { RunIfPending(); } } catch (Exception ex) { if (LogicalThread.CurrentThread != m_thread) { m_thread.Push(Priority, () => { string message = $"Exception occurred while executing logical thread operation: {ex.Message}"; throw new Exception(message, ex); }); } RunIfPending(); if (LogicalThread.CurrentThread == m_thread) { throw; } } }
/// <summary> /// Posts the <paramref name="continuation"/> back to the current context. /// </summary> /// <param name="continuation">The action to invoke asynchronously.</param> /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null.</exception> public void OnCompleted(Action continuation) { if (continuation is null) { throw new ArgumentNullException(nameof(continuation)); } LogicalThread thread = Awaitable.Thread ?? new LogicalThread(); int priority = Awaitable.Priority; if (priority > 0) { thread.Push(priority, continuation); } else { thread.Push(continuation); } }