public void Should_not_call_processor_when_queue_is_empty() { var worker = new TestProcessor(); var target = new WorkerThread<int>("test", TimeSpan.FromMilliseconds(10), worker.Process); worker.Go.WaitOne(TimeSpan.FromSeconds(1)).Should().Be.False(); }
public void Test() { var th = new WorkerThread(); // #if false { var a = th.StartNew(Worker0); while (!a.Wait(0)) { Thread.Sleep(1); } Assert.AreEqual(1, Worker0Count); } { var a = th.StartNew(Worker1, 0); while (!a.Wait(0)) { Thread.Sleep(1); } Assert.AreEqual(1, Worker1Count); } #endif { var a = th.StartNew(Worker2); while (!a.Wait(0)) { Thread.Sleep(1); } Assert.AreEqual(1, Worker2Count); } { var a = th.StartNew(Worker3, 0); while (!a.Wait(0)) { Thread.Sleep(1); } Assert.AreEqual(1, Worker3Count); } }
public SynchronizationContextMock() { CallQueued = new Semaphore(0, Int32.MaxValue); m_WorkItemQueue = new Queue<WorkItem>(); m_WorkerThread = new WorkerThread("SynchronizationContextMockThread", this); }
public void DoWorkShouldNotCallWorkItemDequeueWhenWorkerThreadManagerShouldExitWorkerThreadReturnsTrue() { WorkerThreadManagerStub workerThreadManager = WorkerThreadManagerStub.Create(); ManualResetEvent manualResetEvent = new ManualResetEvent(false); IWorkItemQueue workItemQueue = Substitute.For<IWorkItemQueue>(); WorkerThread workerThread = new WorkerThread(workerThreadManager, workItemQueue, "Test", false); workerThreadManager.WorkerThreadExiting += (sender, args) => { if (args.WorkerThreadExitReason == WorkerThreadExitReason.MaximumThreadCountExceeded) { manualResetEvent.Set(); } }; workerThreadManager.ShouldExitWorkerThread(workerThread, false).ReturnsForAnyArgs(true); workerThread.Start(); manualResetEvent.WaitOne(500); workerThread.Stop(); Wait.While(() => workerThread.Thread.IsAlive, 300); Assert.AreEqual(false, workerThread.Thread.IsAlive); workItemQueue.DidNotReceive().Dequeue(); }
public CustomThreadPool(int NumberOfThreads) { WorkerThreads = new WorkerThread[NumberOfThreads]; for (int n = 0; n < NumberOfThreads; n++) { WorkerThreads[n] = new WorkerThread(); } }
/// <summary> /// İşçi Thread havuzu yeni bir işçi Thread'i başlatıyor olay argümanları sınıfı inşacı metodu. /// </summary> /// <param name="currentNumberOfWorkerThreads">Mevcut işçi thread sayısı.</param> /// <param name="workerThread">İşçi Thread.</param> public WorkerThreadPoolStartingNewWorkerThreadEventArgs(int currentNumberOfWorkerThreads, WorkerThread workerThread) { if (workerThread == null) { throw new ArgumentNullException("workerThread"); } m_CurrentNumberOfWorkerThreads = currentNumberOfWorkerThreads; m_WorkerThread = workerThread; }
/// <summary> /// Constructs a new scheduler /// </summary> /// <param name="connection">The database connection</param> /// <param name="worker">The worker thread</param> /// <param name="datalock">The database lock object</param> public Scheduler(WorkerThread<Server.Runner.IRunnerData> worker) { m_thread = new Thread(new ThreadStart(Runner)); m_worker = worker; m_worker.CompletedWork += OnCompleted; m_schedule = new ISchedule[0]; m_terminate = false; m_event = new AutoResetEvent(false); m_updateTasks = new Dictionary<Server.Runner.IRunnerData, Tuple<ISchedule, DateTime, DateTime>>(); m_thread.IsBackground = true; m_thread.Name = "TaskScheduler"; m_thread.Start(); }
public void Should_be_able_to_dispose_failing_worker() { var worker = new TestProcessor(); var target = new WorkerThread<int>("test", TimeSpan.FromDays(1), worker.Process); target.Enqueue(1); target.Dispose(); worker.Logs.Should().Have.SameSequenceAs(new[] { "1" }); }
public ThreadPoolSynchronizer(uint poolSize,string poolName) { if(poolSize == 0) { throw new InvalidOperationException("Pool size cannot be zero"); } CallQueued = new Semaphore(0,Int32.MaxValue); m_WorkItemQueue = new Queue<WorkItem>(); m_WorkerThreads = new WorkerThread[poolSize]; for(int index = 0;index<poolSize;index++) { m_WorkerThreads[index] = new WorkerThread(poolName + " " + (index+1),this); } }
public void Should_dequeue_all_when_disposing() { var worker = new TestProcessor(); var target = new WorkerThread<int>("test", TimeSpan.FromDays(1), worker.Process); target.Enqueue(1); target.Enqueue(2); target.Enqueue(3); target.Dispose(); worker.Logs.Should().Have.SameSequenceAs(new[] { "1, 2, 3" }); }
/// <summary> /// Add a new callback function to the worker thread. /// </summary> public static void Add(CallbackFunction fn, object param) { if (mInstance == null) { GameObject go = new GameObject("_WorkerThread"); DontDestroyOnLoad(go); mInstance = go.AddComponent<WorkerThread>(); mInstance.mThread = new Thread(mInstance.ThreadFunction); mInstance.mThread.Start(); } Entry ent = new Entry(); ent.fnct = fn; ent.param = param; lock (mInstance) mInstance.mActive.Add(ent); }
/// <summary> /// Blocks until all the ReceivingThreads are started. /// </summary> public override void Start() { Logger.Info("Starting service '" + ServiceName + "'."); Logger.Info("Configuration: " + this.PrettyFormat()); for (int i = 0; i < NumberOfWorkingThreads; i++) { WorkerThread t = new WorkerThread("Receiving thread " + i.ToString("00"), ReceiveOneMessageFromTransport); t.Stopped += (x, e) => { if (e.Error != null) { WorkerThread worker = (WorkerThread)x; Logger.Error(worker.Id + " threw an exception", e.Error); } }; ReceivingThreads.Add(t); t.Start(); } }
public CoreDriver(UIWindow uiWindow, Configuration config) { IsDisposed = false; try { _config = config; _inputAggregator = new InputAggregator(); _buttonStates = SnesJoypadButtons.None; _workerThread = new WorkerThread(); _workerThread.DoWork(() => { _uiWindow = uiWindow; _snes = new Snes(); _snes.VideoUpdated += Snes_VideoUpdated; _snes.AudioUpdated += Snes_AudioUpdated; _snes.SetControllerPortDevice(1, SnesDevice.Joypad); _inputAggregator.InputReceived += InputAggregator_InputReceived; _isAudioSynced = true; _isVideoSynced = false; _isRunning = false; _stopwatch = new Stopwatch(); _stopwatch.Start(); _frameCount = 0; }); _workerThread.WaitFor(); } catch { Dispose(); throw; } }
public void StartShouldStartThread() { WorkerThreadManagerStub workerThreadManager = WorkerThreadManagerStub.Create(); IWorkItemQueue workItemQueue = Substitute.For<IWorkItemQueue>(); workItemQueue.Dequeue().Returns((IWorkItem)null); WorkerThread workerThread = new WorkerThread(workerThreadManager, workItemQueue, "Test", false); workerThreadManager.ShouldExitWorkerThread(workerThread, false).Returns(false); workerThread.Start(); Wait.While(() => !workerThread.Thread.IsAlive, 300); Assert.AreEqual(true, workerThread.Thread.IsAlive); workerThread.Stop(); Wait.While(() => workerThread.Thread.IsAlive, 300); Assert.AreEqual(false, workerThread.Thread.IsAlive); }
public void Should_dequeue_in_batch() { var worker = new TestProcessor(); var target = new WorkerThread<int>("test", TimeSpan.FromSeconds(.75), worker.Process); target.Enqueue(1); target.Enqueue(2); target.Enqueue(3); worker.Go.WaitOne(); target.Enqueue(4); target.Enqueue(5); target.Enqueue(6); worker.Go.WaitOne(); worker.Logs.Should().Have.SameSequenceAs(new[] { "1, 2, 3", "4, 5, 6" }); }
internal void RequestWorker() { Interlocked.Increment(ref _numRequestedWorkers); WorkerThread.MaybeAddWorkingWorker(); GateThread.EnsureRunning(); }
public void CreateTypeBuilderIsThreadSafe() { const int WORKERS = 20; WorkerThread[] workers = new WorkerThread[WORKERS]; for(int i=0;i<WORKERS;i++) { workers[i] = new WorkerThread(new WaitCallback(CallCreateTypeBuilder), i); workers[i].Start(); } for(int i=0;i<WORKERS;i++) { workers[i].Join(); Assert.AreEqual(null, workers[i].Exception); } }
public override void DoWork(WorkerThread workerThread) { }
public static async Task RunBot() { try { newBot = new TelegramBot(botToken); // botDetail = (User)await newBot.MakeRequestAsync(new GetMe()); var botDetail = await newBot.MakeRequestAsync(new GetMe()); Console.WriteLine("UserName Is {0}", botDetail.Username); Session = new Hashtable(); long offset = 0; while (true) { try { Update[] updates = await newBot.MakeRequestAsync(new GetUpdates() { Offset = offset }); if (updates.Length == 0) { continue; } Console.WriteLine(""); if ((updates[0].Message != null)) { Console.WriteLine(updates[0].Message.Chat.Id.ToString() + "-" + updates[0].Message.Text + " in Main Loop"); } else { Console.WriteLine(updates[0].UpdateId); } foreach (var update in updates) { // Console.ReadLine(); WorkerThread worker = new WorkerThread(update); if ((update.Message != null)) { Console.WriteLine(update.Message.Chat.Id.ToString() + "-" + update.Message.Text + " Worker Thread Created"); } else { Console.WriteLine(update.UpdateId); } Thread t = new Thread(new ThreadStart(worker.ThreadProc)); if ((update.Message != null)) { Console.WriteLine(update.Message.Chat.Id.ToString() + "-" + update.Message.Text + " Thread Created"); } else { Console.WriteLine(update.UpdateId); } t.Start(); offset = update.UpdateId + 1; } } catch (Exception ex) { Console.WriteLine(" Exception:" + ex.Message); } } } catch (Exception e) { Console.WriteLine(" Exception:" + e.Message); } }
public async Task TestWorkerThread() { await WorkerThread.RunWorkerThread(); }
execute(ThreadPoolWorkItem workItem) { _m.Lock(); try { Debug.Assert(!_destroyed); if(_workItems.Count == 0) { _m.Notify(); } _workItems.Enqueue(workItem); // // If this is a dynamic thread pool which can still grow and if all threads are // currently busy dispatching or about to dispatch, we spawn a new thread to // execute this new work item right away. // if(_threads.Count < _sizeMax && (_inUse + _workItems.Count) > _threads.Count && !_destroyed) { if(_instance.traceLevels().threadPool >= 1) { string s = "growing " + _prefix + ": Size = " + (_threads.Count + 1); _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s); } try { WorkerThread t = new WorkerThread(this, _threadPrefix + "-" + _threadIndex++); if(_hasPriority) { t.start(_priority); } else { t.start(ThreadPriority.Normal); } _threads.Add(t); } catch(System.Exception ex) { string s = "cannot create thread for `" + _prefix + "':\n" + ex; _instance.initializationData().logger.error(s); } } } finally { _m.Unlock(); } }
/// <summary> /// Creates the worker threads. /// </summary> /// <param name="threadCount">The thread count.</param> /// <returns></returns> protected internal virtual IList CreateWorkerThreads(int threadCount) { workers = new ArrayList(); for (int i = 1; i <= threadCount; ++i) { WorkerThread wt = new WorkerThread( this, string.Format(CultureInfo.InvariantCulture, "{0}-{1}", ThreadNamePrefix, i), ThreadPriority, MakeThreadsDaemons); workers.Add(wt); } return workers; }
/// <summary> /// Starts the worker thread once the window is loaded. /// </summary> /// <param name="sender">Window.</param> /// <param name="e">Event arguments.</param> private void StartWorkerThread(object sender, RoutedEventArgs e) { workerThread = new WorkerThread(ref cameras); workerThread.ResultReady += ResultReady; }
private static void GateThreadStart() { bool disableStarvationDetection = AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.DisableStarvationDetection", false); bool debuggerBreakOnWorkStarvation = AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.DebugBreakOnWorkerStarvation", false); // The first reading is over a time range other than what we are focusing on, so we do not use the read other // than to send it to any runtime-specific implementation that may also use the CPU utilization. CpuUtilizationReader cpuUtilizationReader = default; _ = cpuUtilizationReader.CurrentUtilization; PortableThreadPool threadPoolInstance = ThreadPoolInstance; LowLevelLock hillClimbingThreadAdjustmentLock = threadPoolInstance._hillClimbingThreadAdjustmentLock; while (true) { s_runGateThreadEvent.WaitOne(); bool needGateThreadForRuntime; do { Thread.Sleep(GateThreadDelayMs); if (ThreadPool.EnableWorkerTracking && PortableThreadPoolEventSource.Log.IsEnabled()) { PortableThreadPoolEventSource.Log.ThreadPoolWorkingThreadCount( (uint)threadPoolInstance.GetAndResetHighWatermarkCountOfThreadsProcessingUserCallbacks()); } int cpuUtilization = cpuUtilizationReader.CurrentUtilization; threadPoolInstance._cpuUtilization = cpuUtilization; needGateThreadForRuntime = ThreadPool.PerformRuntimeSpecificGateActivities(cpuUtilization); if (!disableStarvationDetection && threadPoolInstance._separated.numRequestedWorkers > 0 && SufficientDelaySinceLastDequeue(threadPoolInstance)) { try { hillClimbingThreadAdjustmentLock.Acquire(); ThreadCounts counts = threadPoolInstance._separated.counts.VolatileRead(); // Don't add a thread if we're at max or if we are already in the process of adding threads. // This logic is slightly different from the native implementation in CoreCLR because there are // no retired threads. In the native implementation, when hill climbing reduces the thread count // goal, threads that are stopped from processing work are switched to "retired" state, and they // don't count towards the equivalent existing thread count. In this implementation, the // existing thread count includes any worker thread that has not yet exited, including those // stopped from working by hill climbing, so here the number of threads processing work, instead // of the number of existing threads, is compared with the goal. There may be alternative // solutions, for now this is only to maintain consistency in behavior. while ( counts.NumExistingThreads < threadPoolInstance._maxThreads && counts.NumProcessingWork >= counts.NumThreadsGoal) { if (debuggerBreakOnWorkStarvation) { Debugger.Break(); } ThreadCounts newCounts = counts; short newNumThreadsGoal = (short)(counts.NumProcessingWork + 1); newCounts.NumThreadsGoal = newNumThreadsGoal; ThreadCounts oldCounts = threadPoolInstance._separated.counts.InterlockedCompareExchange(newCounts, counts); if (oldCounts == counts) { HillClimbing.ThreadPoolHillClimber.ForceChange(newNumThreadsGoal, HillClimbing.StateOrTransition.Starvation); WorkerThread.MaybeAddWorkingWorker(threadPoolInstance); break; } counts = oldCounts; } } finally { hillClimbingThreadAdjustmentLock.Release(); } } } while ( needGateThreadForRuntime || threadPoolInstance._separated.numRequestedWorkers > 0 || Interlocked.Decrement(ref threadPoolInstance._separated.gateThreadRunningState) > GetRunningStateForNumRuns(0)); } }
/// <summary> /// Initializes the configuration window. /// </summary> /// <param name="workerThread">Used worker thread.</param> public void InitConfiguration(ref WorkerThread workerThread) { manager = new ConfigurationManager(ref workerThread, instructionsText, instructionsBox, audioInputDeviceVolume, positions, saveButton); this.workerThread = workerThread; UpdateStartButton(); }
public static void StopWatchingLogFile() { WorkerThread.Abort(); Trace.WriteLine("stop watch"); }
public static void StartWatchingLogFile() { WorkerThread.Start(); Trace.WriteLine("starting watching"); }
// // This method must only be called if ShouldAdjustMaxWorkersActive has returned true, *and* // _hillClimbingThreadAdjustmentLock is held. // private void AdjustMaxWorkersActive() { LowLevelLock threadAdjustmentLock = _threadAdjustmentLock; if (!threadAdjustmentLock.TryAcquire()) { // The lock is held by someone else, they will take care of this for us return; } bool addWorker = false; try { // Repeated checks from ShouldAdjustMaxWorkersActive() inside the lock ThreadCounts counts = _separated.counts; if (counts.NumProcessingWork > counts.NumThreadsGoal || _pendingBlockingAdjustment != PendingBlockingAdjustment.None) { return; } long endTime = Stopwatch.GetTimestamp(); double elapsedSeconds = Stopwatch.GetElapsedTime(_currentSampleStartTime, endTime).TotalSeconds; if (elapsedSeconds * 1000 >= _threadAdjustmentIntervalMs / 2) { int currentTicks = Environment.TickCount; int totalNumCompletions = (int)_completionCounter.Count; int numCompletions = totalNumCompletions - _separated.priorCompletionCount; short oldNumThreadsGoal = counts.NumThreadsGoal; int newNumThreadsGoal; (newNumThreadsGoal, _threadAdjustmentIntervalMs) = HillClimbing.ThreadPoolHillClimber.Update(oldNumThreadsGoal, elapsedSeconds, numCompletions); if (oldNumThreadsGoal != (short)newNumThreadsGoal) { _separated.counts.InterlockedSetNumThreadsGoal((short)newNumThreadsGoal); // // If we're increasing the goal, inject a thread. If that thread finds work, it will inject // another thread, etc., until nobody finds work or we reach the new goal. // // If we're reducing the goal, whichever threads notice this first will sleep and timeout themselves. // if (newNumThreadsGoal > oldNumThreadsGoal) { addWorker = true; } } _separated.priorCompletionCount = totalNumCompletions; _separated.nextCompletedWorkRequestsTime = currentTicks + _threadAdjustmentIntervalMs; Volatile.Write(ref _separated.priorCompletedWorkRequestsTime, currentTicks); _currentSampleStartTime = endTime; } } finally { threadAdjustmentLock.Release(); } if (addWorker) { WorkerThread.MaybeAddWorkingWorker(this); } }
public bool SetMinThreads(int workerThreads, int ioCompletionThreads) { if (workerThreads < 0 || ioCompletionThreads < 0) { return(false); } bool addWorker = false; bool wakeGateThread = false; _threadAdjustmentLock.Acquire(); try { if (workerThreads > _maxThreads) { return(false); } if (ThreadPool.UsePortableThreadPoolForIO ? ioCompletionThreads > _legacy_maxIOCompletionThreads : !ThreadPool.CanSetMinIOCompletionThreads(ioCompletionThreads)) { return(false); } if (HasForcedMinThreads && workerThreads != ForcedMinWorkerThreads) { return(false); } if (ThreadPool.UsePortableThreadPoolForIO) { _legacy_minIOCompletionThreads = (short)Math.Max(1, ioCompletionThreads); } else { ThreadPool.SetMinIOCompletionThreads(ioCompletionThreads); } short newMinThreads = (short)Math.Max(1, workerThreads); if (newMinThreads == _minThreads) { return(true); } _minThreads = newMinThreads; if (_numBlockedThreads > 0) { // Blocking adjustment will adjust the goal according to its heuristics if (_pendingBlockingAdjustment != PendingBlockingAdjustment.Immediately) { _pendingBlockingAdjustment = PendingBlockingAdjustment.Immediately; wakeGateThread = true; } } else if (_separated.counts.NumThreadsGoal < newMinThreads) { _separated.counts.InterlockedSetNumThreadsGoal(newMinThreads); if (_separated.numRequestedWorkers > 0) { addWorker = true; } } } finally { _threadAdjustmentLock.Release(); } if (addWorker) { WorkerThread.MaybeAddWorkingWorker(this); } else if (wakeGateThread) { GateThread.Wake(this); } return(true); }
/// <summary> /// Creates a new loader with the specified configuration /// </summary> /// <param name="debugging">True if we are debugging</param> /// <param name="language">Which language are we trying to load</param> /// <param name="loaderTimeLimit"> /// Used to limit how long it takes to create a new instance /// </param> /// <param name="multipleTypeNameResolverFunction"> /// Used to resolve multiple type names found in assembly to a single type name, if null, defaults to names => names.SingleOrDefault() /// /// When we search an assembly for derived types of IAlgorithm, sometimes the assembly will contain multiple matching types. This is the case /// for the QuantConnect.Algorithm assembly in this solution. In order to pick the correct type, consumers must specify how to pick the type, /// that's what this function does, it picks the correct type from the list of types found within the assembly. /// </param> /// <param name="workerThread">The worker thread instance the loader should use</param> public Loader(bool debugging, Language language, TimeSpan loaderTimeLimit, Func <List <string>, string> multipleTypeNameResolverFunction, WorkerThread workerThread = null) { _debugging = debugging; _language = language; _workerThread = workerThread; if (multipleTypeNameResolverFunction == null) { throw new ArgumentNullException("multipleTypeNameResolverFunction"); } _loaderTimeLimit = loaderTimeLimit; _multipleTypeNameResolverFunction = multipleTypeNameResolverFunction; }
/// <summary> /// Run the given <see cref="IThreadRunnable" /> object in the next available /// <see cref="Thread" />. If while waiting the thread pool is asked to /// shut down, the Runnable is executed immediately within a new additional /// thread. /// </summary> /// <param name="runnable">The <see cref="IThreadRunnable" /> to be added.</param> public virtual bool RunInThread(IThreadRunnable runnable) { if (runnable == null) { return false; } lock (nextRunnableLock) { handoffPending = true; // Wait until a worker thread is available while ((availWorkers.Count < 1) && !isShutdown) { try { Monitor.Wait(nextRunnableLock, 500); } catch (ThreadInterruptedException) { } } if (!isShutdown) { WorkerThread wt = (WorkerThread)availWorkers[0]; availWorkers.RemoveAt(0); busyWorkers.Add(wt); wt.Run(runnable); } else { // If the thread pool is going down, execute the Runnable // within a new additional worker thread (no thread from the pool). WorkerThread wt = new WorkerThread(this, "WorkerThread-LastJob", prio, MakeThreadsDaemons, runnable); busyWorkers.Add(wt); workers.Add(wt); wt.Start(); } Monitor.PulseAll(nextRunnableLock); handoffPending = false; } return true; }
public ConfigurationStepSpeaker(ConfigurationManager manager, ref WorkerThread workerThread) { this.manager = manager; this.workerThread = workerThread; }
public Task SetUp (TestSuite suite) { worker = new WorkerThread (); return Task.FromResult<object> (null); }
public void ConstructorShouldNotStartThread() { WorkerThread workerThread = new WorkerThread(Substitute.For <IWorkerThreadManager>(), Substitute.For <IWorkItemQueue>(), "Test", false); Assert.AreEqual(false, workerThread.Thread.IsAlive); }
/// <summary> /// Execute a code block with a maximum limit on time and memory. /// </summary> /// <param name="timeSpan">Timeout in timespan</param> /// <param name="withinCustomLimits">Function used to determine if the codeBlock is within custom limits, such as with algorithm manager /// timing individual time loops, return a non-null and non-empty string with a message indicating the error/reason for stoppage</param> /// <param name="codeBlock">Action codeblock to execute</param> /// <param name="memoryCap">Maximum memory allocation, default 1024Mb</param> /// <param name="sleepIntervalMillis">Sleep interval between each check in ms</param> /// <param name="workerThread">The worker thread instance that will execute the provided action, if null /// will use a <see cref="Task"/></param> /// <returns>True if algorithm exited successfully, false if cancelled because it exceeded limits.</returns> public bool ExecuteWithTimeLimit(TimeSpan timeSpan, Func <IsolatorLimitResult> withinCustomLimits, Action codeBlock, long memoryCap = 1024, int sleepIntervalMillis = 1000, WorkerThread workerThread = null) { workerThread?.Add(codeBlock); var task = workerThread == null //Launch task ? Task.Factory.StartNew(codeBlock, CancellationTokenSource.Token) // wrapper task so we can reuse MonitorTask : Task.Factory.StartNew(() => workerThread.FinishedWorkItem.WaitOne(), CancellationTokenSource.Token); try { return(MonitorTask(task, timeSpan, withinCustomLimits, memoryCap, sleepIntervalMillis)); } catch (Exception) { if (!task.IsCompleted) { // lets free the wrapper task even if the worker thread didn't finish workerThread?.FinishedWorkItem.Set(); } throw; } }
public void ConstructorShouldSetIsBackgroundPropertyOfThread([Values(true, false)] bool isBackground) { WorkerThread workerThread = new WorkerThread(Substitute.For <IWorkerThreadManager>(), Substitute.For <IWorkItemQueue>(), "Test", isBackground); Assert.AreEqual(isBackground, workerThread.Thread.IsBackground); }
/// <summary> /// Adds a thread to the manager. /// </summary> /// <param name="initialization">A function to run to perform any initialization on the new thread.</param> /// <param name="initializationInformation">Data to give the ParameterizedThreadStart for initialization.</param> public void AddThread(Action<object> initialization, object initializationInformation) { lock (workers) { var worker = new WorkerThread(workers.Count, this, initialization, initializationInformation); workers.Add(worker); RemakeLoopSections(); } }
public void DoWorkShouldCallWorkerThreadExceptionEventWhenExceptionOccursOutsideOfWorkItemDoWorkMethod() { WorkerThreadManagerStub workerThreadManager = WorkerThreadManagerStub.Create(); ManualResetEvent manualResetEvent = new ManualResetEvent(false); IWorkItemQueue workItemQueue = Substitute.For <IWorkItemQueue>(); IWorkItem workItem = Substitute.For <IWorkItem>(); workItemQueue.Dequeue().Returns(workItem); Exception invalidCastException = new InvalidCastException(); Exception otherThreadsException = null; bool workerThreadExitingEventIsCalled = false; WorkerThread workerThread = new WorkerThread(workerThreadManager, workItemQueue, "Test", false); workerThreadManager.WorkerThreadStarted += (sender, args) => { throw invalidCastException; }; workerThreadManager.WorkerThreadException += (sender, args) => { try { Assert.AreEqual(invalidCastException, args.Exception); } catch (Exception ex) { otherThreadsException = ex; } }; workerThreadManager.WorkerThreadExiting += (sender, args) => { workerThreadExitingEventIsCalled = true; try { Assert.AreEqual(WorkerThreadExitReason.ExceptionOccurred, args.WorkerThreadExitReason); } catch (Exception ex) { otherThreadsException = ex; } manualResetEvent.Set(); }; workerThread.Start(); Wait.While(() => !workerThread.Thread.IsAlive, 300); manualResetEvent.WaitOne(500); workerThread.Stop(); Wait.While(() => workerThread.Thread.IsAlive, 300); Assert.AreEqual(false, workerThread.Thread.IsAlive); Assert.AreEqual(true, workerThreadExitingEventIsCalled); if (otherThreadsException != null) { throw otherThreadsException; } }
/// <summary> /// Creates the worker threads. /// </summary> /// <param name="threadCount">The thread count.</param> /// <returns></returns> protected virtual IList<WorkerThread> CreateWorkerThreads(int threadCount) { workers = new List<WorkerThread>(); for (int i = 1; i <= threadCount; ++i) { string threadPrefix = ThreadNamePrefix; if (threadPrefix == null) { threadPrefix = schedulerInstanceName + "_Worker"; } var workerThread = new WorkerThread( this, string.Format(CultureInfo.InvariantCulture, "{0}-{1}", threadPrefix, i), ThreadPriority, MakeThreadsDaemons); workers.Add(workerThread); } return workers; }
/// <summary> /// Runs a single backtest/live job from the job queue /// </summary> /// <param name="job">The algorithm job to be processed</param> /// <param name="manager"></param> /// <param name="assemblyPath">The path to the algorithm's assembly</param> public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemblyPath) { var marketHoursDatabaseTask = Task.Run(() => StaticInitializations()); var algorithm = default(IAlgorithm); var algorithmManager = manager; try { //Reset thread holders. var initializeComplete = false; Thread threadResults = null; Thread threadRealTime = null; Thread threadAlphas = null; WorkerThread workerThread = null; //-> Initialize messaging system _systemHandlers.Notify.SetAuthentication(job); //-> Set the result handler type for this algorithm job, and launch the associated result thread. _algorithmHandlers.Results.Initialize(job, _systemHandlers.Notify, _systemHandlers.Api, _algorithmHandlers.Setup, _algorithmHandlers.Transactions); threadResults = new Thread(_algorithmHandlers.Results.Run, 0) { IsBackground = true, Name = "Result Thread" }; threadResults.Start(); IBrokerage brokerage = null; DataManager dataManager = null; var synchronizer = _liveMode ? new LiveSynchronizer() : new Synchronizer(); try { // we get the mhdb before creating the algorithm instance, // since the algorithm constructor will use it var marketHoursDatabase = marketHoursDatabaseTask.Result; // start worker thread workerThread = new WorkerThread(); _algorithmHandlers.Setup.WorkerThread = workerThread; // Save algorithm to cache, load algorithm instance: algorithm = _algorithmHandlers.Setup.CreateAlgorithmInstance(job, assemblyPath); // Set algorithm in ILeanManager _systemHandlers.LeanManager.SetAlgorithm(algorithm); // initialize the alphas handler with the algorithm instance _algorithmHandlers.Alphas.Initialize(job, algorithm, _systemHandlers.Notify, _systemHandlers.Api); // Initialize the brokerage IBrokerageFactory factory; brokerage = _algorithmHandlers.Setup.CreateBrokerage(job, algorithm, out factory); var symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder(); var securityService = new SecurityService(algorithm.Portfolio.CashBook, marketHoursDatabase, symbolPropertiesDatabase, (ISecurityInitializerProvider)algorithm); algorithm.Securities.SetSecurityService(securityService); dataManager = new DataManager(_algorithmHandlers.DataFeed, new UniverseSelection( algorithm, securityService), algorithm, algorithm.TimeKeeper, marketHoursDatabase, _liveMode); _algorithmHandlers.Results.SetDataManager(dataManager); algorithm.SubscriptionManager.SetDataManager(dataManager); synchronizer.Initialize(algorithm, dataManager); // Initialize the data feed before we initialize so he can intercept added securities/universes via events _algorithmHandlers.DataFeed.Initialize( algorithm, job, _algorithmHandlers.Results, _algorithmHandlers.MapFileProvider, _algorithmHandlers.FactorFileProvider, _algorithmHandlers.DataProvider, dataManager, (IDataFeedTimeProvider)synchronizer); // set the order processor on the transaction manager (needs to be done before initializing BrokerageHistoryProvider) algorithm.Transactions.SetOrderProcessor(_algorithmHandlers.Transactions); algorithm.SetOrderEventProvider(_algorithmHandlers.Transactions); // set the history provider before setting up the algorithm var historyProvider = GetHistoryProvider(job.HistoryProvider); if (historyProvider is BrokerageHistoryProvider) { (historyProvider as BrokerageHistoryProvider).SetBrokerage(brokerage); } var historyDataCacheProvider = new ZipDataCacheProvider(_algorithmHandlers.DataProvider, isDataEphemeral: _liveMode); historyProvider.Initialize( new HistoryProviderInitializeParameters( job, _systemHandlers.Api, _algorithmHandlers.DataProvider, historyDataCacheProvider, _algorithmHandlers.MapFileProvider, _algorithmHandlers.FactorFileProvider, progress => { // send progress updates to the result handler only during initialization if (!algorithm.GetLocked() || algorithm.IsWarmingUp) { _algorithmHandlers.Results.SendStatusUpdate(AlgorithmStatus.History, string.Format("Processing history {0}%...", progress)); } } ) ); historyProvider.InvalidConfigurationDetected += (sender, args) => { _algorithmHandlers.Results.ErrorMessage(args.Message); }; historyProvider.NumericalPrecisionLimited += (sender, args) => { _algorithmHandlers.Results.DebugMessage(args.Message); }; historyProvider.DownloadFailed += (sender, args) => { _algorithmHandlers.Results.ErrorMessage(args.Message, args.StackTrace); }; historyProvider.ReaderErrorDetected += (sender, args) => { _algorithmHandlers.Results.RuntimeError(args.Message, args.StackTrace); }; algorithm.HistoryProvider = historyProvider; // initialize the default brokerage message handler algorithm.BrokerageMessageHandler = factory.CreateBrokerageMessageHandler(algorithm, job, _systemHandlers.Api); //Initialize the internal state of algorithm and job: executes the algorithm.Initialize() method. initializeComplete = _algorithmHandlers.Setup.Setup(new SetupHandlerParameters(dataManager.UniverseSelection, algorithm, brokerage, job, _algorithmHandlers.Results, _algorithmHandlers.Transactions, _algorithmHandlers.RealTime)); // set this again now that we've actually added securities _algorithmHandlers.Results.SetAlgorithm(algorithm); // alpha handler needs start/end dates to determine sample step sizes _algorithmHandlers.Alphas.OnAfterAlgorithmInitialized(algorithm); //If there are any reasons it failed, pass these back to the IDE. if (!initializeComplete || algorithm.ErrorMessages.Count > 0 || _algorithmHandlers.Setup.Errors.Count > 0) { initializeComplete = false; //Get all the error messages: internal in algorithm and external in setup handler. var errorMessage = String.Join(",", algorithm.ErrorMessages); errorMessage += String.Join(",", _algorithmHandlers.Setup.Errors.Select(e => { var message = e.Message; if (e.InnerException != null) { var err = _exceptionInterpreter.Value.Interpret(e.InnerException, _exceptionInterpreter.Value); message += _exceptionInterpreter.Value.GetExceptionMessageHeader(err); } return(message); })); Log.Error("Engine.Run(): " + errorMessage); _algorithmHandlers.Results.RuntimeError(errorMessage); _systemHandlers.Api.SetAlgorithmStatus(job.AlgorithmId, AlgorithmStatus.RuntimeError, errorMessage); } } catch (Exception err) { Log.Error(err); var runtimeMessage = "Algorithm.Initialize() Error: " + err.Message + " Stack Trace: " + err; _algorithmHandlers.Results.RuntimeError(runtimeMessage, err.ToString()); _systemHandlers.Api.SetAlgorithmStatus(job.AlgorithmId, AlgorithmStatus.RuntimeError, runtimeMessage); } // log the job endpoints Log.Trace("JOB HANDLERS: "); Log.Trace(" DataFeed: " + _algorithmHandlers.DataFeed.GetType().FullName); Log.Trace(" Setup: " + _algorithmHandlers.Setup.GetType().FullName); Log.Trace(" RealTime: " + _algorithmHandlers.RealTime.GetType().FullName); Log.Trace(" Results: " + _algorithmHandlers.Results.GetType().FullName); Log.Trace(" Transactions: " + _algorithmHandlers.Transactions.GetType().FullName); Log.Trace(" Alpha: " + _algorithmHandlers.Alphas.GetType().FullName); if (algorithm?.HistoryProvider != null) { Log.Trace(" History Provider: " + algorithm.HistoryProvider.GetType().FullName); } if (job is LiveNodePacket) { Log.Trace(" Brokerage: " + brokerage?.GetType().FullName); } //-> Using the job + initialization: load the designated handlers: if (initializeComplete) { // notify the LEAN manager that the algorithm is initialized and starting _systemHandlers.LeanManager.OnAlgorithmStart(); //-> Reset the backtest stopwatch; we're now running the algorithm. var startTime = DateTime.Now; //Set algorithm as locked; set it to live mode if we're trading live, and set it to locked for no further updates. algorithm.SetAlgorithmId(job.AlgorithmId); algorithm.SetLocked(); //Load the associated handlers for transaction and realtime events: _algorithmHandlers.Transactions.Initialize(algorithm, brokerage, _algorithmHandlers.Results); _algorithmHandlers.RealTime.Setup(algorithm, job, _algorithmHandlers.Results, _systemHandlers.Api); // wire up the brokerage message handler brokerage.Message += (sender, message) => { algorithm.BrokerageMessageHandler.Handle(message); // fire brokerage message events algorithm.OnBrokerageMessage(message); switch (message.Type) { case BrokerageMessageType.Disconnect: algorithm.OnBrokerageDisconnect(); break; case BrokerageMessageType.Reconnect: algorithm.OnBrokerageReconnect(); break; } }; //Send status to user the algorithm is now executing. _algorithmHandlers.Results.SendStatusUpdate(AlgorithmStatus.Running); //Launch the data, transaction and realtime handlers into dedicated threads threadRealTime = new Thread(_algorithmHandlers.RealTime.Run) { IsBackground = true, Name = "RealTime Thread" }; threadAlphas = new Thread(() => _algorithmHandlers.Alphas.Run()) { IsBackground = true, Name = "Alpha Thread" }; //Launch the data feed, result sending, and transaction models/handlers in separate threads. threadRealTime.Start(); // RealTime scan time for time based events: threadAlphas.Start(); // Alpha thread for processing algorithm alpha insights // Result manager scanning message queue: (started earlier) _algorithmHandlers.Results.DebugMessage(string.Format("Launching analysis for {0} with LEAN Engine v{1}", job.AlgorithmId, Globals.Version)); try { //Create a new engine isolator class var isolator = new Isolator(); // Execute the Algorithm Code: var complete = isolator.ExecuteWithTimeLimit(_algorithmHandlers.Setup.MaximumRuntime, algorithmManager.TimeLoopWithinLimits, () => { try { //Run Algorithm Job: // -> Using this Data Feed, // -> Send Orders to this TransactionHandler, // -> Send Results to ResultHandler. algorithmManager.Run(job, algorithm, synchronizer, _algorithmHandlers.Transactions, _algorithmHandlers.Results, _algorithmHandlers.RealTime, _systemHandlers.LeanManager, _algorithmHandlers.Alphas, isolator.CancellationToken); } catch (Exception err) { //Debugging at this level is difficult, stack trace needed. Log.Error(err); algorithm.RunTimeError = err; algorithmManager.SetStatus(AlgorithmStatus.RuntimeError); return; } Log.Trace("Engine.Run(): Exiting Algorithm Manager"); }, job.Controls.RamAllocation, workerThread: workerThread); if (!complete) { Log.Error("Engine.Main(): Failed to complete in time: " + _algorithmHandlers.Setup.MaximumRuntime.ToString("F")); throw new Exception("Failed to complete algorithm within " + _algorithmHandlers.Setup.MaximumRuntime.ToString("F") + " seconds. Please make it run faster."); } // Algorithm runtime error: if (algorithm.RunTimeError != null) { HandleAlgorithmError(job, algorithm.RunTimeError); } } catch (Exception err) { //Error running the user algorithm: purge datafeed, send error messages, set algorithm status to failed. HandleAlgorithmError(job, err); } // notify the LEAN manager that the algorithm has finished _systemHandlers.LeanManager.OnAlgorithmEnd(); try { var trades = algorithm.TradeBuilder.ClosedTrades; var charts = new Dictionary <string, Chart>(_algorithmHandlers.Results.Charts); var orders = new Dictionary <int, Order>(_algorithmHandlers.Transactions.Orders); var holdings = new Dictionary <string, Holding>(); var banner = new Dictionary <string, string>(); var statisticsResults = new StatisticsResults(); var csvTransactionsFileName = Config.Get("transaction-log"); if (!string.IsNullOrEmpty(csvTransactionsFileName)) { SaveListOfTrades(_algorithmHandlers.Transactions, csvTransactionsFileName); } try { //Generates error when things don't exist (no charting logged, runtime errors in main algo execution) const string strategyEquityKey = "Strategy Equity"; const string equityKey = "Equity"; const string dailyPerformanceKey = "Daily Performance"; const string benchmarkKey = "Benchmark"; // make sure we've taken samples for these series before just blindly requesting them if (charts.ContainsKey(strategyEquityKey) && charts[strategyEquityKey].Series.ContainsKey(equityKey) && charts[strategyEquityKey].Series.ContainsKey(dailyPerformanceKey) && charts.ContainsKey(benchmarkKey) && charts[benchmarkKey].Series.ContainsKey(benchmarkKey) ) { var equity = charts[strategyEquityKey].Series[equityKey].Values; var performance = charts[strategyEquityKey].Series[dailyPerformanceKey].Values; var profitLoss = new SortedDictionary <DateTime, decimal>(algorithm.Transactions.TransactionRecord); var totalTransactions = algorithm.Transactions.GetOrders(x => x.Status.IsFill()).Count(); var benchmark = charts[benchmarkKey].Series[benchmarkKey].Values; statisticsResults = StatisticsBuilder.Generate(trades, profitLoss, equity, performance, benchmark, _algorithmHandlers.Setup.StartingPortfolioValue, algorithm.Portfolio.TotalFees, totalTransactions); //Some users have $0 in their brokerage account / starting cash of $0. Prevent divide by zero errors var netReturn = _algorithmHandlers.Setup.StartingPortfolioValue > 0 ? (algorithm.Portfolio.TotalPortfolioValue - _algorithmHandlers.Setup.StartingPortfolioValue) / _algorithmHandlers.Setup.StartingPortfolioValue : 0; //Add other fixed parameters. banner.Add("Unrealized", "$" + algorithm.Portfolio.TotalUnrealizedProfit.ToString("N2")); banner.Add("Fees", "-$" + algorithm.Portfolio.TotalFees.ToString("N2")); banner.Add("Net Profit", "$" + algorithm.Portfolio.TotalProfit.ToString("N2")); banner.Add("Return", netReturn.ToString("P")); banner.Add("Equity", "$" + algorithm.Portfolio.TotalPortfolioValue.ToString("N2")); } } catch (Exception err) { Log.Error(err, "Error generating statistics packet"); } //Diagnostics Completed, Send Result Packet: var totalSeconds = (DateTime.Now - startTime).TotalSeconds; var dataPoints = algorithmManager.DataPoints + algorithm.HistoryProvider.DataPointCount; if (!_liveMode) { var kps = dataPoints / (double)1000 / totalSeconds; _algorithmHandlers.Results.DebugMessage($"Algorithm Id:({job.AlgorithmId}) completed in {totalSeconds:F2} seconds at {kps:F0}k data points per second. Processing total of {dataPoints:N0} data points."); } _algorithmHandlers.Results.SendFinalResult(job, orders, algorithm.Transactions.TransactionRecord, holdings, algorithm.Portfolio.CashBook, statisticsResults, banner); } catch (Exception err) { Log.Error(err, "Error sending analysis results"); } //Before we return, send terminate commands to close up the threads _algorithmHandlers.Transactions.Exit(); _algorithmHandlers.DataFeed.Exit(); _algorithmHandlers.RealTime.Exit(); _algorithmHandlers.Alphas.Exit(); dataManager?.RemoveAllSubscriptions(); workerThread?.Dispose(); } //Close result handler: _algorithmHandlers.Results.Exit(); //Wait for the threads to complete: var millisecondInterval = 10; var millisecondTotalWait = 0; while ((_algorithmHandlers.Results.IsActive || (_algorithmHandlers.Transactions != null && _algorithmHandlers.Transactions.IsActive) || (_algorithmHandlers.DataFeed != null && _algorithmHandlers.DataFeed.IsActive) || (_algorithmHandlers.RealTime != null && _algorithmHandlers.RealTime.IsActive) || (_algorithmHandlers.Alphas != null && _algorithmHandlers.Alphas.IsActive)) && millisecondTotalWait < 30 * 1000) { Thread.Sleep(millisecondInterval); if (millisecondTotalWait % (millisecondInterval * 10) == 0) { Log.Trace("Waiting for threads to exit..."); } millisecondTotalWait += millisecondInterval; } //Terminate threads still in active state. if (threadResults != null && threadResults.IsAlive) { threadResults.Abort(); } if (threadAlphas != null && threadAlphas.IsAlive) { threadAlphas.Abort(); } if (brokerage != null) { Log.Trace("Engine.Run(): Disconnecting from brokerage..."); brokerage.Disconnect(); brokerage.Dispose(); } if (_algorithmHandlers.Setup != null) { Log.Trace("Engine.Run(): Disposing of setup handler..."); _algorithmHandlers.Setup.Dispose(); } Log.Trace("Engine.Main(): Analysis Completed and Results Posted."); } catch (Exception err) { Log.Error(err, "Error running algorithm"); } finally { //No matter what for live mode; make sure we've set algorithm status in the API for "not running" conditions: if (_liveMode && algorithmManager.State != AlgorithmStatus.Running && algorithmManager.State != AlgorithmStatus.RuntimeError) { _systemHandlers.Api.SetAlgorithmStatus(job.AlgorithmId, algorithmManager.State); } _algorithmHandlers.Results.Exit(); _algorithmHandlers.DataFeed.Exit(); _algorithmHandlers.Transactions.Exit(); _algorithmHandlers.RealTime.Exit(); } }
/// <summary> /// /// </summary> public override void Start() { WorkerThread.Start(); Paused = false; }
public ThreadPool(Instance instance, string prefix, int timeout) { Ice.Properties properties = instance.initializationData().properties; _instance = instance; _dispatcher = instance.initializationData().dispatcher; _destroyed = false; _prefix = prefix; _threadIndex = 0; _inUse = 0; _serialize = properties.getPropertyAsInt(_prefix + ".Serialize") > 0; _serverIdleTime = timeout; string programName = properties.getProperty("Ice.ProgramName"); if(programName.Length > 0) { _threadPrefix = programName + "-" + _prefix; } else { _threadPrefix = _prefix; } // // We use just one thread as the default. This is the fastest // possible setting, still allows one level of nesting, and // doesn't require to make the servants thread safe. // int size = properties.getPropertyAsIntWithDefault(_prefix + ".Size", 1); if(size < 1) { string s = _prefix + ".Size < 1; Size adjusted to 1"; _instance.initializationData().logger.warning(s); size = 1; } int sizeMax = properties.getPropertyAsIntWithDefault(_prefix + ".SizeMax", size); if(sizeMax < size) { string s = _prefix + ".SizeMax < " + _prefix + ".Size; SizeMax adjusted to Size (" + size + ")"; _instance.initializationData().logger.warning(s); sizeMax = size; } int sizeWarn = properties.getPropertyAsInt(_prefix + ".SizeWarn"); if(sizeWarn != 0 && sizeWarn < size) { string s = _prefix + ".SizeWarn < " + _prefix + ".Size; adjusted SizeWarn to Size (" + size + ")"; _instance.initializationData().logger.warning(s); sizeWarn = size; } else if(sizeWarn > sizeMax) { string s = _prefix + ".SizeWarn > " + _prefix + ".SizeMax; adjusted SizeWarn to SizeMax (" + sizeMax + ")"; _instance.initializationData().logger.warning(s); sizeWarn = sizeMax; } int threadIdleTime = properties.getPropertyAsIntWithDefault(_prefix + ".ThreadIdleTime", 60); if(threadIdleTime < 0) { string s = _prefix + ".ThreadIdleTime < 0; ThreadIdleTime adjusted to 0"; _instance.initializationData().logger.warning(s); threadIdleTime = 0; } _size = size; _sizeMax = sizeMax; _sizeWarn = sizeWarn; _threadIdleTime = threadIdleTime; int stackSize = properties.getPropertyAsInt(_prefix + ".StackSize"); if(stackSize < 0) { string s = _prefix + ".StackSize < 0; Size adjusted to OS default"; _instance.initializationData().logger.warning(s); stackSize = 0; } _stackSize = stackSize; _hasPriority = properties.getProperty(_prefix + ".ThreadPriority").Length > 0; _priority = IceInternal.Util.stringToThreadPriority(properties.getProperty(_prefix + ".ThreadPriority")); if(!_hasPriority) { _hasPriority = properties.getProperty("Ice.ThreadPriority").Length > 0; _priority = IceInternal.Util.stringToThreadPriority(properties.getProperty("Ice.ThreadPriority")); } if(_instance.traceLevels().threadPool >= 1) { string s = "creating " + _prefix + ": Size = " + _size + ", SizeMax = " + _sizeMax + ", SizeWarn = " + _sizeWarn; _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s); } _workItems = new Queue<ThreadPoolWorkItem>(); try { _threads = new List<WorkerThread>(); for(int i = 0; i < _size; ++i) { WorkerThread thread = new WorkerThread(this, _threadPrefix + "-" + _threadIndex++); if(_hasPriority) { thread.start(_priority); } else { thread.start(ThreadPriority.Normal); } _threads.Add(thread); } } catch(System.Exception ex) { string s = "cannot create thread for `" + _prefix + "':\n" + ex; _instance.initializationData().logger.error(s); destroy(); joinWithAllThreads(); throw; } }
/// <summary> /// Runs a single backtest/live job from the job queue /// </summary> /// <param name="job">The algorithm job to be processed</param> /// <param name="manager">The algorithm manager instance</param> /// <param name="assemblyPath">The path to the algorithm's assembly</param> /// <param name="workerThread">The worker thread instance</param> public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemblyPath, WorkerThread workerThread) { var marketHoursDatabaseTask = Task.Run(() => StaticInitializations()); var algorithm = default(IAlgorithm); var algorithmManager = manager; try { TextSubscriptionDataSourceReader.SetCacheSize((int)(job.RamAllocation * 0.4)); //Reset thread holders. var initializeComplete = false; //-> Initialize messaging system SystemHandlers.Notify.SetAuthentication(job); //-> Set the result handler type for this algorithm job, and launch the associated result thread. AlgorithmHandlers.Results.Initialize(job, SystemHandlers.Notify, SystemHandlers.Api, AlgorithmHandlers.Transactions); IBrokerage brokerage = null; DataManager dataManager = null; IDataCacheProvider historyDataCacheProvider = null; var synchronizer = _liveMode ? new LiveSynchronizer() : new Synchronizer(); try { // we get the mhdb before creating the algorithm instance, // since the algorithm constructor will use it var marketHoursDatabase = marketHoursDatabaseTask.Result; AlgorithmHandlers.Setup.WorkerThread = workerThread; // Save algorithm to cache, load algorithm instance: algorithm = AlgorithmHandlers.Setup.CreateAlgorithmInstance(job, assemblyPath); // Set algorithm in ILeanManager SystemHandlers.LeanManager.SetAlgorithm(algorithm); // initialize the alphas handler with the algorithm instance AlgorithmHandlers.Alphas.Initialize(job, algorithm, SystemHandlers.Notify, SystemHandlers.Api, AlgorithmHandlers.Transactions); // initialize the object store AlgorithmHandlers.ObjectStore.Initialize(algorithm.Name, job.UserId, job.ProjectId, job.UserToken, job.Controls); // initialize the data permission manager AlgorithmHandlers.DataPermissionsManager.Initialize(job); // notify the user of any errors w/ object store persistence AlgorithmHandlers.ObjectStore.ErrorRaised += (sender, args) => algorithm.Debug($"ObjectStore Persistence Error: {args.Error.Message}"); // Initialize the brokerage IBrokerageFactory factory; brokerage = AlgorithmHandlers.Setup.CreateBrokerage(job, algorithm, out factory); // forward brokerage message events to the result handler brokerage.Message += (_, e) => AlgorithmHandlers.Results.BrokerageMessage(e); var symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder(); var mapFilePrimaryExchangeProvider = new MapFilePrimaryExchangeProvider(AlgorithmHandlers.MapFileProvider); var registeredTypesProvider = new RegisteredSecurityDataTypesProvider(); var securityService = new SecurityService(algorithm.Portfolio.CashBook, marketHoursDatabase, symbolPropertiesDatabase, algorithm, registeredTypesProvider, new SecurityCacheProvider(algorithm.Portfolio), mapFilePrimaryExchangeProvider); algorithm.Securities.SetSecurityService(securityService); dataManager = new DataManager(AlgorithmHandlers.DataFeed, new UniverseSelection( algorithm, securityService, AlgorithmHandlers.DataPermissionsManager, AlgorithmHandlers.DataProvider), algorithm, algorithm.TimeKeeper, marketHoursDatabase, _liveMode, registeredTypesProvider, AlgorithmHandlers.DataPermissionsManager); algorithm.SubscriptionManager.SetDataManager(dataManager); synchronizer.Initialize(algorithm, dataManager); // Initialize the data feed before we initialize so he can intercept added securities/universes via events AlgorithmHandlers.DataFeed.Initialize( algorithm, job, AlgorithmHandlers.Results, AlgorithmHandlers.MapFileProvider, AlgorithmHandlers.FactorFileProvider, AlgorithmHandlers.DataProvider, dataManager, (IDataFeedTimeProvider)synchronizer, AlgorithmHandlers.DataPermissionsManager.DataChannelProvider); // set the order processor on the transaction manager (needs to be done before initializing BrokerageHistoryProvider) algorithm.Transactions.SetOrderProcessor(AlgorithmHandlers.Transactions); // set the history provider before setting up the algorithm var historyProvider = GetHistoryProvider(); historyProvider.SetBrokerage(brokerage); historyDataCacheProvider = new ZipDataCacheProvider(AlgorithmHandlers.DataProvider, isDataEphemeral: _liveMode); historyProvider.Initialize( new HistoryProviderInitializeParameters( job, SystemHandlers.Api, AlgorithmHandlers.DataProvider, historyDataCacheProvider, AlgorithmHandlers.MapFileProvider, AlgorithmHandlers.FactorFileProvider, progress => { // send progress updates to the result handler only during initialization if (!algorithm.GetLocked() || algorithm.IsWarmingUp) { AlgorithmHandlers.Results.SendStatusUpdate(AlgorithmStatus.History, Invariant($"Processing history {progress}%...")); } }, // disable parallel history requests for live trading parallelHistoryRequestsEnabled: !_liveMode, dataPermissionManager: AlgorithmHandlers.DataPermissionsManager ) ); historyProvider.InvalidConfigurationDetected += (sender, args) => { AlgorithmHandlers.Results.ErrorMessage(args.Message); }; historyProvider.DownloadFailed += (sender, args) => { AlgorithmHandlers.Results.ErrorMessage(args.Message, args.StackTrace); }; historyProvider.ReaderErrorDetected += (sender, args) => { AlgorithmHandlers.Results.RuntimeError(args.Message, args.StackTrace); }; algorithm.HistoryProvider = historyProvider; // initialize the default brokerage message handler algorithm.BrokerageMessageHandler = factory.CreateBrokerageMessageHandler(algorithm, job, SystemHandlers.Api); //Initialize the internal state of algorithm and job: executes the algorithm.Initialize() method. initializeComplete = AlgorithmHandlers.Setup.Setup(new SetupHandlerParameters(dataManager.UniverseSelection, algorithm, brokerage, job, AlgorithmHandlers.Results, AlgorithmHandlers.Transactions, AlgorithmHandlers.RealTime, AlgorithmHandlers.ObjectStore, AlgorithmHandlers.DataProvider)); // set this again now that we've actually added securities AlgorithmHandlers.Results.SetAlgorithm(algorithm, AlgorithmHandlers.Setup.StartingPortfolioValue); // alpha handler needs start/end dates to determine sample step sizes AlgorithmHandlers.Alphas.OnAfterAlgorithmInitialized(algorithm); //If there are any reasons it failed, pass these back to the IDE. if (!initializeComplete || algorithm.ErrorMessages.Count > 0 || AlgorithmHandlers.Setup.Errors.Count > 0) { initializeComplete = false; //Get all the error messages: internal in algorithm and external in setup handler. var errorMessage = string.Join(",", algorithm.ErrorMessages); errorMessage += string.Join(",", AlgorithmHandlers.Setup.Errors.Select(e => { var message = e.Message; if (e.InnerException != null) { var interpreter = StackExceptionInterpreter.Instance.Value; var err = interpreter.Interpret(e.InnerException); message += interpreter.GetExceptionMessageHeader(err); } return(message); })); Log.Error("Engine.Run(): " + errorMessage); AlgorithmHandlers.Results.RuntimeError(errorMessage); SystemHandlers.Api.SetAlgorithmStatus(job.AlgorithmId, AlgorithmStatus.RuntimeError, errorMessage); } } catch (Exception err) { Log.Error(err); // for python we don't add the ugly pythonNet stack trace var stackTrace = job.Language == Language.Python ? err.Message : err.ToString(); var runtimeMessage = "Algorithm.Initialize() Error: " + err.Message + " Stack Trace: " + stackTrace; AlgorithmHandlers.Results.RuntimeError(runtimeMessage, stackTrace); SystemHandlers.Api.SetAlgorithmStatus(job.AlgorithmId, AlgorithmStatus.RuntimeError, runtimeMessage); } // log the job endpoints Log.Trace("JOB HANDLERS: "); Log.Trace(" DataFeed: " + AlgorithmHandlers.DataFeed.GetType().FullName); Log.Trace(" Setup: " + AlgorithmHandlers.Setup.GetType().FullName); Log.Trace(" RealTime: " + AlgorithmHandlers.RealTime.GetType().FullName); Log.Trace(" Results: " + AlgorithmHandlers.Results.GetType().FullName); Log.Trace(" Transactions: " + AlgorithmHandlers.Transactions.GetType().FullName); Log.Trace(" Alpha: " + AlgorithmHandlers.Alphas.GetType().FullName); Log.Trace(" ObjectStore: " + AlgorithmHandlers.ObjectStore.GetType().FullName); if (algorithm?.HistoryProvider != null) { Log.Trace(" History Provider: " + algorithm.HistoryProvider.GetType().FullName); } if (job is LiveNodePacket) { Log.Trace(" Brokerage: " + brokerage?.GetType().FullName); } //-> Using the job + initialization: load the designated handlers: if (initializeComplete) { // notify the LEAN manager that the algorithm is initialized and starting SystemHandlers.LeanManager.OnAlgorithmStart(); //-> Reset the backtest stopwatch; we're now running the algorithm. var startTime = DateTime.UtcNow; //Set algorithm as locked; set it to live mode if we're trading live, and set it to locked for no further updates. algorithm.SetAlgorithmId(job.AlgorithmId); algorithm.SetLocked(); //Load the associated handlers for transaction and realtime events: AlgorithmHandlers.Transactions.Initialize(algorithm, brokerage, AlgorithmHandlers.Results); AlgorithmHandlers.RealTime.Setup(algorithm, job, AlgorithmHandlers.Results, SystemHandlers.Api, algorithmManager.TimeLimit); // wire up the brokerage message handler brokerage.Message += (sender, message) => { algorithm.BrokerageMessageHandler.Handle(message); // fire brokerage message events algorithm.OnBrokerageMessage(message); switch (message.Type) { case BrokerageMessageType.Disconnect: algorithm.OnBrokerageDisconnect(); break; case BrokerageMessageType.Reconnect: algorithm.OnBrokerageReconnect(); break; } }; //Send status to user the algorithm is now executing. AlgorithmHandlers.Results.SendStatusUpdate(AlgorithmStatus.Running); // Result manager scanning message queue: (started earlier) AlgorithmHandlers.Results.DebugMessage( $"Launching analysis for {job.AlgorithmId} with LEAN Engine v{Globals.Version}"); try { //Create a new engine isolator class var isolator = new Isolator(); // Execute the Algorithm Code: var complete = isolator.ExecuteWithTimeLimit(AlgorithmHandlers.Setup.MaximumRuntime, algorithmManager.TimeLimit.IsWithinLimit, () => { try { //Run Algorithm Job: // -> Using this Data Feed, // -> Send Orders to this TransactionHandler, // -> Send Results to ResultHandler. algorithmManager.Run(job, algorithm, synchronizer, AlgorithmHandlers.Transactions, AlgorithmHandlers.Results, AlgorithmHandlers.RealTime, SystemHandlers.LeanManager, AlgorithmHandlers.Alphas, isolator.CancellationToken); } catch (Exception err) { algorithm.SetRuntimeError(err, "AlgorithmManager.Run"); return; } Log.Trace("Engine.Run(): Exiting Algorithm Manager"); }, job.Controls.RamAllocation, workerThread: workerThread); if (!complete) { Log.Error("Engine.Main(): Failed to complete in time: " + AlgorithmHandlers.Setup.MaximumRuntime.ToStringInvariant("F")); throw new Exception("Failed to complete algorithm within " + AlgorithmHandlers.Setup.MaximumRuntime.ToStringInvariant("F") + " seconds. Please make it run faster."); } } catch (Exception err) { //Error running the user algorithm: purge datafeed, send error messages, set algorithm status to failed. algorithm.SetRuntimeError(err, "Engine Isolator"); } // Algorithm runtime error: if (algorithm.RunTimeError != null) { HandleAlgorithmError(job, algorithm.RunTimeError); } // notify the LEAN manager that the algorithm has finished SystemHandlers.LeanManager.OnAlgorithmEnd(); try { var csvTransactionsFileName = Config.Get("transaction-log"); if (!string.IsNullOrEmpty(csvTransactionsFileName)) { SaveListOfTrades(AlgorithmHandlers.Transactions, csvTransactionsFileName); } if (!_liveMode) { //Diagnostics Completed, Send Result Packet: var totalSeconds = (DateTime.UtcNow - startTime).TotalSeconds; var dataPoints = algorithmManager.DataPoints + algorithm.HistoryProvider.DataPointCount; var kps = dataPoints / (double)1000 / totalSeconds; AlgorithmHandlers.Results.DebugMessage($"Algorithm Id:({job.AlgorithmId}) completed in {totalSeconds:F2} seconds at {kps:F0}k data points per second. Processing total of {dataPoints:N0} data points."); } } catch (Exception err) { Log.Error(err, "Error sending analysis results"); } //Before we return, send terminate commands to close up the threads AlgorithmHandlers.Transactions.Exit(); AlgorithmHandlers.RealTime.Exit(); dataManager?.RemoveAllSubscriptions(); workerThread?.Dispose(); } synchronizer.DisposeSafely(); // Close data feed, alphas. Could be running even if algorithm initialization failed AlgorithmHandlers.DataFeed.Exit(); AlgorithmHandlers.Alphas.Exit(); //Close result handler: AlgorithmHandlers.Results.Exit(); //Wait for the threads to complete: var millisecondInterval = 10; var millisecondTotalWait = 0; while ((AlgorithmHandlers.Results.IsActive || (AlgorithmHandlers.Transactions != null && AlgorithmHandlers.Transactions.IsActive) || (AlgorithmHandlers.DataFeed != null && AlgorithmHandlers.DataFeed.IsActive) || (AlgorithmHandlers.RealTime != null && AlgorithmHandlers.RealTime.IsActive) || (AlgorithmHandlers.Alphas != null && AlgorithmHandlers.Alphas.IsActive)) && millisecondTotalWait < 30 * 1000) { Thread.Sleep(millisecondInterval); if (millisecondTotalWait % (millisecondInterval * 10) == 0) { Log.Trace("Waiting for threads to exit..."); } millisecondTotalWait += millisecondInterval; } if (brokerage != null) { Log.Trace("Engine.Run(): Disconnecting from brokerage..."); brokerage.Disconnect(); brokerage.Dispose(); } if (AlgorithmHandlers.Setup != null) { Log.Trace("Engine.Run(): Disposing of setup handler..."); AlgorithmHandlers.Setup.Dispose(); } historyDataCacheProvider.DisposeSafely(); Log.Trace("Engine.Main(): Analysis Completed and Results Posted."); } catch (Exception err) { Log.Error(err, "Error running algorithm"); } finally { //No matter what for live mode; make sure we've set algorithm status in the API for "not running" conditions: if (_liveMode && algorithmManager.State != AlgorithmStatus.Running && algorithmManager.State != AlgorithmStatus.RuntimeError) { SystemHandlers.Api.SetAlgorithmStatus(job.AlgorithmId, algorithmManager.State); } AlgorithmHandlers.Results.Exit(); AlgorithmHandlers.DataFeed.Exit(); AlgorithmHandlers.Transactions.Exit(); AlgorithmHandlers.RealTime.Exit(); } }
private void run(WorkerThread thread) { ThreadPoolWorkItem workItem = null; while(true) { lock(this) { if(workItem != null) { Debug.Assert(_inUse > 0); --_inUse; if(_workItems.Count == 0) { thread.setState(Ice.Instrumentation.ThreadState.ThreadStateIdle); } } workItem = null; while(_workItems.Count == 0) { if(_destroyed) { return; } if(_threadIdleTime > 0) { if(!System.Threading.Monitor.Wait(this, _threadIdleTime * 1000) && _workItems.Count == 0) // If timeout { if(_destroyed) { return; } else if(_serverIdleTime == 0 || _threads.Count > 1) { // // If not the last thread or if server idle time isn't configured, // we can exit. Unlike C++/Java, there's no need to have a thread // always spawned in the thread pool because all the IO is done // by the .NET thread pool threads. Instead, we'll just spawn a // new thread when needed (i.e.: when a new work item is queued). // if(_instance.traceLevels().threadPool >= 1) { string s = "shrinking " + _prefix + ": Size=" + (_threads.Count - 1); _instance.initializationData().logger.trace( _instance.traceLevels().threadPoolCat, s); } _threads.Remove(thread); _instance.asyncIOThread().queue(() => { thread.join(); }); return; } else { Debug.Assert(_serverIdleTime > 0 && _inUse == 0 && _threads.Count == 1); if(!System.Threading.Monitor.Wait(this, _serverIdleTime * 1000) && _workItems.Count == 0) { if(!_destroyed) { _workItems.Enqueue(() => { try { _instance.objectAdapterFactory().shutdown(); } catch(Ice.CommunicatorDestroyedException) { } }); } } } } } else { System.Threading.Monitor.Wait(this); } } Debug.Assert(_workItems.Count > 0); workItem = _workItems.Dequeue(); Debug.Assert(_inUse >= 0); ++_inUse; thread.setState(Ice.Instrumentation.ThreadState.ThreadStateInUseForUser); if(_sizeMax > 1 && _inUse == _sizeWarn) { string s = "thread pool `" + _prefix + "' is running low on threads\n" + "Size=" + _size + ", " + "SizeMax=" + _sizeMax + ", " + "SizeWarn=" + _sizeWarn; _instance.initializationData().logger.warning(s); } } try { workItem(); } catch(System.Exception ex) { string s = "exception in `" + _prefix + "' while calling on work item:\n" + ex + '\n'; _instance.initializationData().logger.error(s); } } }
internal void CreateWorkThread() { fWorkerThread = new WorkerThread(true); }
void MonitoredSystem_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (!DataModel.Instance.IsPowerwall) { StackTrace stackTrace = new StackTrace(); if (!stackTrace.ToString().Contains("DataModel")) { DateTime updateTime = DateTime.Now; switch (e.PropertyName) { case "State": this.LastUpdate = updateTime; WorkerThread workerThreadState = ThreadManager.CreateWorkerThread("BackSync_MonitoredSystem.State", () => { List <Tuple <string, DateTime> > paramList = new List <Tuple <string, DateTime> >(); paramList.Add(new Tuple <string, DateTime>(this.MAC, updateTime)); bool result; if (this.State == MappingState.Maintenance) { result = DataModel.Instance.SyncBackMonitoredSystemMaintenanceActivated(paramList); } else { result = DataModel.Instance.SyncBackMonitoredSystemMaintenanceDeactivated(paramList); } }, false); break; case "ResetDate": this.LastUpdate = updateTime; WorkerThread workerThreadResetDate = ThreadManager.CreateWorkerThread("BackSync_MonitoredSystem.ResetDate", () => { List <Tuple <string, DateTime> > paramList = new List <Tuple <string, DateTime> >(); paramList.Add(new Tuple <string, DateTime>(this.MAC, updateTime)); bool result = DataModel.Instance.SyncBackMonitoredSystemResetDateUpdated(paramList); }, false); break; case "OuID": this.LastUpdate = updateTime; WorkerThread workerThreadOuID = ThreadManager.CreateWorkerThread("BackSync_MonitoredSystem.OuID", () => { List <Tuple <string, int, DateTime> > paramList = new List <Tuple <string, int, DateTime> >(); paramList.Add(new Tuple <string, int, DateTime>(this.MAC, this.OuID, updateTime)); bool result = DataModel.Instance.SyncBackMonitoredSystemMoved(paramList); }, false); break; case "LastUpdate": /* Do nothing */ break; case "Name": this.LastUpdate = updateTime; Console.WriteLine(">>> NAME CHANGED"); WorkerThread workerThreadName = ThreadManager.CreateWorkerThread("BackSync_MonitoredSystem.Name", () => { List <Tuple <string, string, DateTime> > paramList = new List <Tuple <string, string, DateTime> >(); paramList.Add(new Tuple <string, string, DateTime>(this.MAC, this.Name, updateTime)); bool result = DataModel.Instance.SyncBackMonitoredSystemName(paramList); }, false); break; default: break; } } stackTrace = null; } }
private WorkerThread AddWorkerThread() { lock (workerThreads) { var result = new WorkerThread(Process); workerThreads.Add(result); result.Stopped += delegate(object sender, EventArgs e) { var wt = sender as WorkerThread; lock (workerThreads) workerThreads.Remove(wt); }; return result; } }
/// <summary> /// Initialize the debugger /// </summary> /// <param name="algorithmNodePacket">The algorithm node packet</param> /// <param name="workerThread">The worker thread instance to use</param> public static bool InitializeDebugging(AlgorithmNodePacket algorithmNodePacket, WorkerThread workerThread) { var isolator = new Isolator(); return(isolator.ExecuteWithTimeLimit(TimeSpan.FromMinutes(5), () => DebuggerHelper.Initialize(algorithmNodePacket.Language), algorithmNodePacket.RamAllocation, sleepIntervalMillis: 100, workerThread: workerThread)); }
protected void MakeAvailable(WorkerThread wt) { lock (nextRunnableLock) { if (!isShutdown) { availWorkers.Add(wt); } busyWorkers.Remove(wt); Monitor.PulseAll(nextRunnableLock); } }
public ThreadPool(Instance instance, string prefix, int timeout) { Ice.Properties properties = instance.initializationData().properties; _instance = instance; _dispatcher = instance.initializationData().dispatcher; _destroyed = false; _prefix = prefix; _threadIndex = 0; _inUse = 0; _serialize = properties.getPropertyAsInt(_prefix + ".Serialize") > 0; _serverIdleTime = timeout; string programName = properties.getProperty("Ice.ProgramName"); if (programName.Length > 0) { _threadPrefix = programName + "-" + _prefix; } else { _threadPrefix = _prefix; } // // We use just one thread as the default. This is the fastest // possible setting, still allows one level of nesting, and // doesn't require to make the servants thread safe. // int size = properties.getPropertyAsIntWithDefault(_prefix + ".Size", 1); if (size < 1) { string s = _prefix + ".Size < 1; Size adjusted to 1"; _instance.initializationData().logger.warning(s); size = 1; } int sizeMax = properties.getPropertyAsIntWithDefault(_prefix + ".SizeMax", size); if (sizeMax < size) { string s = _prefix + ".SizeMax < " + _prefix + ".Size; SizeMax adjusted to Size (" + size + ")"; _instance.initializationData().logger.warning(s); sizeMax = size; } int sizeWarn = properties.getPropertyAsInt(_prefix + ".SizeWarn"); if (sizeWarn != 0 && sizeWarn < size) { string s = _prefix + ".SizeWarn < " + _prefix + ".Size; adjusted SizeWarn to Size (" + size + ")"; _instance.initializationData().logger.warning(s); sizeWarn = size; } else if (sizeWarn > sizeMax) { string s = _prefix + ".SizeWarn > " + _prefix + ".SizeMax; adjusted SizeWarn to SizeMax (" + sizeMax + ")"; _instance.initializationData().logger.warning(s); sizeWarn = sizeMax; } int threadIdleTime = properties.getPropertyAsIntWithDefault(_prefix + ".ThreadIdleTime", 60); if (threadIdleTime < 0) { string s = _prefix + ".ThreadIdleTime < 0; ThreadIdleTime adjusted to 0"; _instance.initializationData().logger.warning(s); threadIdleTime = 0; } _size = size; _sizeMax = sizeMax; _sizeWarn = sizeWarn; _threadIdleTime = threadIdleTime; int stackSize = properties.getPropertyAsInt(_prefix + ".StackSize"); if (stackSize < 0) { string s = _prefix + ".StackSize < 0; Size adjusted to OS default"; _instance.initializationData().logger.warning(s); stackSize = 0; } _stackSize = stackSize; _priority = properties.getProperty(_prefix + ".ThreadPriority").Length > 0 ? Util.stringToThreadPriority(properties.getProperty(_prefix + ".ThreadPriority")) : Util.stringToThreadPriority(properties.getProperty("Ice.ThreadPriority")); if (_instance.traceLevels().threadPool >= 1) { string s = "creating " + _prefix + ": Size = " + _size + ", SizeMax = " + _sizeMax + ", SizeWarn = " + _sizeWarn; _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s); } _workItems = new Queue <ThreadPoolWorkItem>(); try { _threads = new List <WorkerThread>(); for (int i = 0; i < _size; ++i) { WorkerThread thread = new WorkerThread(this, _threadPrefix + "-" + _threadIndex++); thread.start(_priority); _threads.Add(thread); } } catch (System.Exception ex) { string s = "cannot create thread for `" + _prefix + "':\n" + ex; _instance.initializationData().logger.error(s); destroy(); joinWithAllThreads(); throw; } }
protected virtual void ClearFromBusyWorkersList(WorkerThread wt) { lock(nextRunnableLock) { busyWorkers.Remove(wt); Monitor.PulseAll(nextRunnableLock); } }
private void run(WorkerThread thread) { ThreadPoolWorkItem workItem = null; while (true) { lock (this) { if (workItem != null) { Debug.Assert(_inUse > 0); --_inUse; if (_workItems.Count == 0) { thread.setState(Ice.Instrumentation.ThreadState.ThreadStateIdle); } } workItem = null; while (_workItems.Count == 0) { if (_destroyed) { return; } if (_threadIdleTime > 0) { if (!Monitor.Wait(this, _threadIdleTime * 1000) && _workItems.Count == 0) // If timeout { if (_destroyed) { return; } else if (_serverIdleTime == 0 || _threads.Count > 1) { // // If not the last thread or if server idle time isn't configured, // we can exit. Unlike C++/Java, there's no need to have a thread // always spawned in the thread pool because all the IO is done // by the .NET thread pool threads. Instead, we'll just spawn a // new thread when needed (i.e.: when a new work item is queued). // if (_instance.traceLevels().threadPool >= 1) { string s = "shrinking " + _prefix + ": Size=" + (_threads.Count - 1); _instance.initializationData().logger.trace( _instance.traceLevels().threadPoolCat, s); } _threads.Remove(thread); _instance.asyncIOThread().queue(() => { thread.join(); }); return; } else { Debug.Assert(_serverIdleTime > 0 && _inUse == 0 && _threads.Count == 1); if (!Monitor.Wait(this, _serverIdleTime * 1000) && _workItems.Count == 0) { if (!_destroyed) { _workItems.Enqueue(() => { try { _instance.objectAdapterFactory().shutdown(); } catch (Ice.CommunicatorDestroyedException) { } }); } } } } } else { Monitor.Wait(this); } } Debug.Assert(_workItems.Count > 0); workItem = _workItems.Dequeue(); Debug.Assert(_inUse >= 0); ++_inUse; thread.setState(Ice.Instrumentation.ThreadState.ThreadStateInUseForUser); if (_sizeMax > 1 && _inUse == _sizeWarn) { string s = "thread pool `" + _prefix + "' is running low on threads\n" + "Size=" + _size + ", " + "SizeMax=" + _sizeMax + ", " + "SizeWarn=" + _sizeWarn; _instance.initializationData().logger.warning(s); } } try { workItem(); } catch (System.Exception ex) { string s = "exception in `" + _prefix + "' while calling on work item:\n" + ex + '\n'; _instance.initializationData().logger.error(s); } } }
public Task TearDown (TestSuite suite) { worker.Stop (); worker = null; return Task.FromResult<object> (null); }
public FrmMain() { InitializeComponent(); worker = new WorkerThread(Done); }
/// <summary> /// Terminate any worker threads in this thread group. /// Jobs currently in progress will complete. /// </summary> public virtual void Shutdown(bool waitForJobsToComplete) { // Give waiting (wait(1000)) worker threads a chance to shut down. // Active worker threads will shut down after finishing their // current job. lock (nextRunnableLock) { isShutdown = true; if (workers == null) // case where the pool wasn't even initialize()ed { return; } // signal each worker thread to shut down for (int i = 0; i < workers.Count; i++) { if (workers[i] != null) { workers[i].Shutdown(); } } Monitor.PulseAll(nextRunnableLock); if (waitForJobsToComplete) { // wait for hand-off in runInThread to complete... while (handoffPending) { try { Monitor.Wait(nextRunnableLock, 100); } catch (ThreadInterruptedException) { } } // Wait until all worker threads are shut down while (busyWorkers.Count > 0) { LinkedListNode <WorkerThread> wt = busyWorkers.First; try { // note: with waiting infinite time the // application may appear to 'hang'. Monitor.Wait(nextRunnableLock, 2000); } catch (ThreadInterruptedException) { } } while (workers.Count > 0) { int index = workers.Count - 1; WorkerThread wt = workers[index]; try { wt.Join(); workers.RemoveAt(index); } catch (ThreadStateException) { } } } } }
/// <summary> /// Execute a code block with a maximum limit on time and memory. /// </summary> /// <param name="timeSpan">Timeout in timespan</param> /// <param name="codeBlock">Action codeblock to execute</param> /// <param name="memoryCap">Maximum memory allocation, default 1024Mb</param> /// <param name="sleepIntervalMillis">Sleep interval between each check in ms</param> /// <param name="workerThread">The worker thread instance that will execute the provided action, if null /// will use a <see cref="Task"/></param> /// <returns>True if algorithm exited successfully, false if cancelled because it exceeded limits.</returns> public bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock, long memoryCap, int sleepIntervalMillis = 1000, WorkerThread workerThread = null) { return(ExecuteWithTimeLimit(timeSpan, null, codeBlock, memoryCap, sleepIntervalMillis, workerThread)); }
public void dispatch(System.Action call, Ice.Connection con) { lock(this) { if(_destroyed) { throw new Ice.CommunicatorDestroyedException(); } _workItems.Enqueue(() => { dispatchFromThisThread(call, con); }); System.Threading.Monitor.Pulse(this); // // If this is a dynamic thread pool which can still grow and if all threads are // currently busy dispatching or about to dispatch, we spawn a new thread to // execute this new work item right away. // if(_threads.Count < _sizeMax && (_inUse + _workItems.Count) > _threads.Count && !_destroyed) { if(_instance.traceLevels().threadPool >= 1) { string s = "growing " + _prefix + ": Size = " + (_threads.Count + 1); _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s); } try { WorkerThread t = new WorkerThread(this, _threadPrefix + "-" + _threadIndex++); if(_hasPriority) { t.start(_priority); } else { t.start(ThreadPriority.Normal); } _threads.Add(t); } catch(System.Exception ex) { string s = "cannot create thread for `" + _prefix + "':\n" + ex; _instance.initializationData().logger.error(s); } } } }
public void SetUp() { _workerThread = new TestWorkerThread(); }
_workingThread = new Thread(new ThreadStart(WorkerThread));
/// <summary> /// Terminate any worker threads in this thread group. /// Jobs currently in progress will complete. /// </summary> public virtual void Shutdown(bool waitForJobsToComplete) { // Give waiting (wait(1000)) worker threads a chance to shut down. // Active worker threads will shut down after finishing their // current job. lock (nextRunnableLock) { log.Debug("Shutting down threadpool..."); isShutdown = true; if (workers == null) // case where the pool wasn't even initialize()ed { return; } // signal each worker thread to shut down foreach (WorkerThread thread in workers) { if (thread != null) { thread.Shutdown(); } } Monitor.PulseAll(nextRunnableLock); if (waitForJobsToComplete) { // wait for hand-off in runInThread to complete... while (handoffPending) { try { Monitor.Wait(nextRunnableLock, 100); } catch (ThreadInterruptedException) { } } // Wait until all worker threads are shut down while (busyWorkers.Count > 0) { LinkedListNode <WorkerThread> wt = busyWorkers.First; try { log.DebugFormat(CultureInfo.InvariantCulture, "Waiting for thread {0} to shut down", wt.Value.Name); // note: with waiting infinite time the // application may appear to 'hang'. Monitor.Wait(nextRunnableLock, 2000); } catch (ThreadInterruptedException) { } } while (workers.Count > 0) { int index = workers.Count - 1; WorkerThread wt = workers[index]; try { wt.Join(); workers.RemoveAt(index); } catch (ThreadStateException) { } } log.Debug("No executing jobs remaining, all threads stopped."); } log.Debug("Shutdown of threadpool complete."); } }