/// <summary> /// Attempts to execute the delegate immediately, on the calling thread, without scheduling. /// </summary> /// <param name="synchronizationObject">Synchronization object.</param> /// <param name="action">Action to execute.</param> /// <param name="startTime">Scheduled start time.</param> /// <param name="context">The scheduler context on which to execute the action.</param> /// <returns>Success flag.</returns> public bool TryExecute(SynchronizationLock synchronizationObject, Action action, DateTime startTime, SchedulerContext context) { if (this.forcedShutdownRequested || startTime > context.FinalizeTime) { return(true); } if (startTime > this.clock.GetCurrentTime() && this.delayFutureWorkitemsUntilDue) { return(false); } if (!this.isSchedulerThread.Value && !this.allowSchedulingOnExternalThreads) { // this thread is not ours, so return return(false); } // try to acquire a lock // however, if this thread already has the lock, we have to give up to keep the no-reentrancy guarantee if (!synchronizationObject.TryLock()) { return(false); } // ExecuteAndRelease assumes that the context has already been entered, so we must explicitly // enter it here. The context will be exited just prior to returning from ExecuteAndRelease. context.Enter(); this.ExecuteAndRelease(synchronizationObject, action, context); this.counters?.Increment(SchedulerCounters.ImmediateWorkitemsPerSecond); return(true); }
/// <summary> /// Attempts to execute the delegate immediately, on the calling thread, without scheduling. /// </summary> /// <typeparam name="T">Action argument type.</typeparam> /// <param name="synchronizationObject">Synchronization object.</param> /// <param name="action">Action to execute.</param> /// <param name="argument">Action argument.</param> /// <param name="startTime">Scheduled start time.</param> /// <param name="context">The scheduler context on which to execute the action.</param> /// <returns>Success flag.</returns> public bool TryExecute <T>(SynchronizationLock synchronizationObject, Action <T> action, T argument, DateTime startTime, SchedulerContext context) { if (this.forcedShutdownRequested || startTime > context.FinalizeTime) { return(true); } if (startTime > this.clock.GetCurrentTime() && this.delayFutureWorkitemsUntilDue) { return(false); } if (!this.isSchedulerThread.Value && !this.allowSchedulingOnExternalThreads) { // this thread is not ours, so return return(false); } // try to acquire a lock on the sync context // however, if this thread already has the lock, we have to give up to keep the no-reentrancy guarantee if (!synchronizationObject.TryLock()) { return(false); } try { // Unlike ExecuteAndRelease, which assumes that the context has already been entered (e.g. // when the work item was first created), we need to explicitly enter the context prior to // running the action. The context will be exited in the finally clause. context.Enter(); action(argument); this.counters?.Increment(SchedulerCounters.WorkitemsPerSecond); this.counters?.Increment(SchedulerCounters.ImmediateWorkitemsPerSecond); } catch (Exception e) when(this.errorHandler(e)) { } finally { synchronizationObject.Release(); context.Exit(); } return(true); }
private static bool TryGetExclusiveLock(SynchronizationLock syncLock) { return(syncLock.TryLock()); }