public void Tick() { var flowBlock = SuppressFlow(); Task[] tasks; lock (m_runningTasks) { tasks = m_runningTasks.Values.ToArray(); } // ticks should be reentrant (Tick might invoke TriggerEvent, e.g.) Dictionary <int, Task> lastInTickTasks; lock (m_inTickTasksLock) { lastInTickTasks = m_inTickTasks; m_inTickTasks = new Dictionary <int, Task>(); } do { using (var scope = new ProfilerScope(() => "task iteration")) { foreach (var task in tasks) { InvokeTryExecuteTask(task); if (task.Exception != null) { Debug.WriteLine("Exception thrown by a task: {0}", task.Exception.ToString()); } if (task.IsCompleted || task.IsFaulted || task.IsCanceled) { lock (m_runningTasks) { m_runningTasks.Remove(task.Id); } } } lock (m_inTickTasksLock) { tasks = m_inTickTasks.Values.ToArray(); m_inTickTasks.Clear(); } } } while (tasks.Length != 0); lock (m_inTickTasksLock) { m_inTickTasks = lastInTickTasks; } flowBlock?.Undo(); }
public void Tick() { IsProfiling = ProfilerIsRecording(); if (GameInterface.SnapshotStackBoundary(out var b)) { ScriptHost.SubmitBoundaryStart(b, b.Length); } try { using (var scope = new ProfilerScope(() => "c# cleanup")) { ScriptContext.GlobalCleanUp(); } using (var scope = new ProfilerScope(() => "c# deferredDelay")) { var delays = ms_delays.ToArray(); var now = DateTime.UtcNow; foreach (var delay in delays) { if (now >= delay.Item1) { using (var inScope = new ProfilerScope(() => delay.Item3)) { try { BaseScript.CurrentName = delay.Item3; delay.Item2(new DummyAsyncResult()); } finally { BaseScript.CurrentName = null; } } ms_delays.Remove(delay); } } } using (var scope = new ProfilerScope(() => "c# schedule")) { foreach (var script in ms_definedScripts.ToArray()) { script.ScheduleRun(); } } using (var scope = new ProfilerScope(() => "c# tasks")) { CitizenTaskScheduler.Instance.Tick(); } using (var scope = new ProfilerScope(() => "c# syncCtx")) { CitizenSynchronizationContext.Tick(); } } catch (Exception e) { PrintError("tick", e); } finally { ScriptHost.SubmitBoundaryStart(null, 0); } }