void CreateLongRunningTask(XParameterizedThreadStart threadStartFunc) { this.task = Task.Factory.StartNew( () => { // We start the task running, then unleash it by signaling the readyToStart event. // This is needed to avoid thread reuse for tasks (see below) this.readyToStart.WaitOne(); // This is the first time we're using this thread, therefore the TLS slot must be empty if (currentThread != null) { Debug.WriteLine("warning: currentThread already created; OS thread reused"); Debug.Assert(false); } currentThread = this; threadStartFunc(this.startupParameter); this.completed.Set(); }, CancellationToken.None, // .NET always creates a brand new thread for LongRunning tasks // This is not documented but unlikely to ever change: // https://github.com/dotnet/corefx/issues/2576#issuecomment-126693306 TaskCreationOptions.LongRunning, TaskScheduler.Default); }
protected bool ConfirmShutdown() { if (!this.IsShuttingDown) { return(false); } Contract.Assert(this.InEventLoop, "must be invoked from an event loop"); this.CancelScheduledTasks(); if (this.gracefulShutdownStartTime == PreciseTimeSpan.Zero) { this.gracefulShutdownStartTime = PreciseTimeSpan.FromStart; } if (this.RunAllTasks() || this.RunShutdownHooks()) { if (this.IsShutdown) { // Executor shut down - no new tasks anymore. return(true); } // There were tasks in the queue. Wait a little bit more until no tasks are queued for the quiet period. this.WakeUp(true); return(false); } PreciseTimeSpan nanoTime = PreciseTimeSpan.FromStart; if (this.IsShutdown || (nanoTime - this.gracefulShutdownStartTime > this.gracefulShutdownTimeout)) { return(true); } if (nanoTime - this.lastExecutionTime <= this.gracefulShutdownQuietPeriod) { // Check if any tasks were added to the queue every 100ms. // TODO: Change the behavior of takeTask() so that it returns on timeout. // todo: ??? this.WakeUp(true); Thread.Sleep(100); return(false); } // No tasks were added for last quiet period - hopefully safe to shut down. // (Hopefully because we really cannot make a guarantee that there will be no execute() calls by a user.) return(true); }
protected SingleThreadEventExecutor(IEventExecutorGroup parent, string threadName, TimeSpan breakoutInterval, IQueue <IRunnable> taskQueue) : base(parent) { this.terminationCompletionSource = new TaskCompletionSource(); this.taskQueue = taskQueue; this.preciseBreakoutInterval = PreciseTimeSpan.FromTimeSpan(breakoutInterval); this.scheduler = new ExecutorTaskScheduler(this); this.thread = new Thread(this.Loop); if (string.IsNullOrEmpty(threadName)) { this.thread.Name = DefaultWorkerThreadName; } else { this.thread.Name = threadName; } this.thread.Start(); }
/// <inheritdoc cref="IEventExecutor"/> public override bool IsInEventLoop(Thread t) => this.thread == t;
/// <inheritdoc cref="IEventExecutor"/> public abstract bool IsInEventLoop(Thread thread);