{"id":330366,"date":"2022-03-06T15:00:08","date_gmt":"2022-03-06T15:00:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=330366"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=330366","title":{"rendered":"<span>\u0422\u0430\u0439\u043c\u0435\u0440 \u0432 .NET \u0441 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u043c 1 \u043c\u0441. macOS<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0439, \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0443\u0436\u0435\u043d \u0442\u0430\u0439\u043c\u0435\u0440 \u0441 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u043c 1 \u043c\u0441. \u0412 \u0441\u0432\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/github.com\/melanchall\/drywetmidi\" rel=\"noopener noreferrer nofollow\"><u>DryWetMIDI<\/u><\/a> \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0442\u0430\u0439\u043c\u0435\u0440 \u0432 \u0440\u043e\u043b\u0438 \u201c\u0434\u0432\u0438\u0433\u0430\u0442\u0435\u043b\u044f\u201d \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f MIDI-\u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u043e \u0432\u0441\u0442\u0443\u043f\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/650021\/\" rel=\"noopener noreferrer nofollow\"><u>\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/u><\/a>. \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043b\u044f Windows \u0438 macOS. \u0421\u0442\u0430\u0442\u044c\u044e \u043f\u043e *nix, \u0443\u0432\u044b, \u0436\u0434\u0430\u0442\u044c \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435 \u0441\u0442\u043e\u0438\u0442.<\/p>\n<p>\u041a \u0441\u043b\u043e\u0432\u0443, \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u0438\u0441\u0430\u043b \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u043f\u043b\u0435\u0435\u0440\u044b \u043f\u043e\u0432\u044b\u0448\u0430\u044e\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430, \u0430 \u044d\u0442\u043e \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443\u0435\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043c\u043e\u0435\u043c\u0443 \u043f\u043e\u0434\u0445\u043e\u0434 \u0441 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u043c \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 (\u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u0432\u0435\u0441\u044c\u043c\u0430 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e), \u0447\u0442\u043e \u044f \u0434\u0435\u043b\u0430\u044e \u043b\u043e\u0436\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u044d\u0442\u0438\u043c\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430\u043c\u0438, \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u2013 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0443 \u0431\u0443\u0444\u0435\u0440 \u0438 \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0430 \u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u0430. \u042f <a href=\"https:\/\/forum.videolan.org\/viewtopic.php?f=2&amp;t=159238\" rel=\"noopener noreferrer nofollow\"><u>\u043d\u0430\u043f\u0438\u0441\u0430\u043b<\/u><\/a> \u043d\u0430 \u0444\u043e\u0440\u0443\u043c VLC, \u0434\u0430\u0431\u044b \u0443\u0442\u043e\u0447\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u0432 \u044d\u0442\u043e\u043c \u043f\u043b\u0435\u0435\u0440\u0435 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e. \u0412\u043e\u0442 \u043e\u0442\u0432\u0435\u0442:<\/p>\n<blockquote>\n<p><em>VLC 3.0 currently compare the media time against a media clock whose parameters are generated from the media timing information. When the clock says that the media time associated with a frame has been reached, it renders the frame. So in a sense, it&#8217;s &#171;like&#187; timers yes, and not tickless or event-driven.<\/em><\/p>\n<\/blockquote>\n<p>\u0422.\u0435. \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c VLC \u0432\u0441\u0451 \u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u201c\u0442\u0430\u0439\u043c\u0435\u0440\u043e\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439\u201d \u043f\u043e\u0434\u0445\u043e\u0434.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0441\u044c \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c macOS, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0431\u044b\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043d\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/pipelines\/agents\/hosted?view=azure-devops\" rel=\"noopener noreferrer nofollow\"><u>Azure Pipelines \u043f\u0443\u043b\u0430 Microsoft<\/u><\/a>, \u0432\u0435\u0440\u0441\u0438\u044f \u041e\u0421 11.0.0. \u0414\u0430, \u044d\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0447\u0435\u0441\u0442\u043d\u043e, \u043d\u043e \u0447\u0442\u043e \u043f\u043e\u0434\u0435\u043b\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u0443 \u043a\u043e\u0433\u043e-\u0442\u043e \u0435\u0441\u0442\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0438 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0436\u0435\u043b\u0435\u0437\u0435, \u044f \u0431\u044b\u043b \u0431\u044b \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u043e, \u0431\u044b\u043b\u0438 \u0431\u044b \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430\u043c\u0438 Intel \u0438 Apple.<\/p>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/h2>\n<p>\u0414\u0430\u0431\u044b \u0441\u0442\u0430\u0442\u044c\u044f \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0431\u044b\u043b\u0430 \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0439 \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u044b\u0433\u0430\u0442\u044c \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439, \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0435\u0449\u0451 \u0440\u0430\u0437 \u043a\u043e\u0434 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u044f.<\/p>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"cs\">using System;  namespace Common {     public interface ITimer     {         void Start(int intervalMs, Action callback);         void Stop();     } }<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u043a\u043e\u0434 \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u0440\u0430 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0441\u0442\u0430\u043b \u0447\u0443\u0442\u044c \u0434\u043b\u0438\u043d\u043d\u0435\u0435. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u044f \u043d\u0435 \u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043b\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u043d\u044f\u0442\u0438\u0435\u043c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u0443\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u0442\u044c\u0438. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 CPU \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0442\u0430\u0439\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cs\">using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading;  namespace Common {     public static class TimerChecker     {         private static readonly TimeSpan MeasurementDuration = TimeSpan.FromMinutes(3);         private static readonly TimeSpan CpuMeasurementInterval = TimeSpan.FromMilliseconds(500);         private static readonly int[] IntervalsToCheck = { 1, 10, 100 };          public static void Check(ITimer timer)         {             Console.WriteLine(\"Starting measuring...\");             Console.WriteLine($\"OS: {Environment.OSVersion}\");             Console.WriteLine($\"CPUs: {Environment.ProcessorCount}\");             Console.WriteLine(\"--------------------------------\");              foreach (var intervalMs in IntervalsToCheck)             {                 Console.WriteLine($\"Measuring interval of {intervalMs} ms...\");                 CheckInterval(timer, intervalMs);             }              Console.WriteLine(\"All done.\");         }          private static void CheckInterval(ITimer timer, int intervalMs)         {             var times = new List&lt;long>((int)Math.Ceiling(MeasurementDuration.TotalMilliseconds));             var cpuUsage = new List&lt;float>((int)Math.Ceiling(MeasurementDuration.TotalMilliseconds \/ CpuMeasurementInterval.TotalMilliseconds));                          var stopwatch = new Stopwatch();                          var cpuTimer = new System.Timers.Timer(CpuMeasurementInterval.TotalMilliseconds);             var cpuStep = 0;              var cpuUsageStopwatch = new Stopwatch();             var startCpuUsage = TimeSpan.Zero;             var startTime = 0L;              cpuTimer.Elapsed += (_, _) =>             {                 if (cpuStep++ > 0)                 {                     var cpuUsedMs = (float)(Process.GetCurrentProcess().TotalProcessorTime - startCpuUsage).TotalMilliseconds;                     var totalMsPassed = cpuUsageStopwatch.ElapsedMilliseconds - startTime;                     var cpuUsageTotal = cpuUsedMs \/ totalMsPassed;                     cpuUsage.Add(cpuUsageTotal * 100);                 }                  startTime = cpuUsageStopwatch.ElapsedMilliseconds;                 startCpuUsage = Process.GetCurrentProcess().TotalProcessorTime;              };                          Action callback = () => times.Add(stopwatch.ElapsedMilliseconds);              timer.Start(intervalMs, callback);             stopwatch.Start();             cpuTimer.Start();             cpuUsageStopwatch.Start();              Thread.Sleep(MeasurementDuration);              timer.Stop();             stopwatch.Stop();             cpuTimer.Stop();                          File.WriteAllLines($\"cpu_{intervalMs}.txt\", cpuUsage.ToArray().Select(u => u.ToString(\"0.##\")));              var deltas = new List&lt;long>();             var lastTime = 0L;              foreach (var time in times.ToArray())             {                 var delta = time - lastTime;                 deltas.Add(delta);                 lastTime = time;             }              File.WriteAllLines($\"deltas_{intervalMs}.txt\", deltas.Select(d => d.ToString()));         }     } }<\/code><\/pre>\n<p>\u0422.\u0435. \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0441\u043d\u0438\u043c\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0435 500 \u043c\u0441 (\u0447\u0435\u0433\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e) \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u0418 \u0434\u0430\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043c\u043d\u043e\u0433\u043e\u044f\u0434\u0435\u0440\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u044f\u0434\u0440\u0443. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443, \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0431\u044b\u043b \u043e\u0434\u043d\u043e\u044f\u0434\u0435\u0440\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 100%, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u044f\u0434\u0440\u0430, \u0430 \u043d\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u0420\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u044b\u043b\u0430 \u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.environment.processorcount\" rel=\"noopener noreferrer nofollow\"><u>Environment.ProcessorCount<\/u><\/a>.<\/p>\n<p>\u041a\u0430\u043a \u0438 \u0440\u0430\u043d\u044c\u0448\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 3 \u043c\u0438\u043d\u0443\u0442 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 1, 10 \u0438 100 \u043c\u0441. \u0413\u0440\u0430\u0444\u0438\u043a\u0438 \u0434\u0435\u043b\u044c\u0442 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 CPU:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/420\/08e\/30e\/42008e30e434d31224b59ce8d8cf1e57.png\" alt=\"\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430\" title=\"\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430\" width=\"1500\" height=\"980\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/420\/08e\/30e\/42008e30e434d31224b59ce8d8cf1e57.png\"\/><figcaption>\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/figcaption><\/figure>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043a\u043e\u0434, \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0432 \u043a\u043e\u043d\u0446\u0435.<\/p>\n<h2>\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b<\/h2>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u043d\u0435\u0441\u0442\u0430\u0440\u0435\u044e\u0449\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0438 \u2013 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b:<\/p>\n<pre><code class=\"cs\">using Common; using System; using System.Diagnostics; using System.Threading;  namespace InfiniteLoopTimer {     internal sealed class Timer : ITimer     {         private bool _running;          public void Start(int intervalMs, Action callback)         {             var thread = new Thread(() =>             {                 var lastTime = 0L;                 var stopwatch = new Stopwatch();                  _running = true;                 stopwatch.Start();                  while (_running)                 {                     if (stopwatch.ElapsedMilliseconds - lastTime &lt; intervalMs)                         continue;                      callback();                     lastTime = stopwatch.ElapsedMilliseconds;                 }             });              thread.Start();         }          public void Stop()         {             _running = false;         }     } }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u0430, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0430\u043a\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d5a\/8a7\/e2c\/d5a8a7e2ccc37d8291e490d144c96796.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d5a\/8a7\/e2c\/d5a8a7e2ccc37d8291e490d144c96796.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a30\/550\/75a\/a3055075ab892aaaa715477397a32958.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a30\/550\/75a\/a3055075ab892aaaa715477397a32958.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/81b\/1e0\/960\/81b1e096003a874a85d9f8e52127d8f3.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/81b\/1e0\/960\/81b1e096003a874a85d9f8e52127d8f3.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0422\u0430\u0439\u043c\u0435\u0440 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u0442\u043e\u0447\u043d\u044b\u0439. \u0418 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043f\u043b\u043e\u0445\u043e\u0439, \u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043f\u0440\u0435\u0431\u044b\u0432\u0430\u0435\u0442 \u0432 \u0433\u0440\u0443\u0441\u0442\u0438 \u043e\u0442 \u0434\u0430\u043d\u043d\u043e\u0439 \u0435\u043c\u0443 \u0437\u0430\u0434\u0430\u0447\u0438. \u0410 \u043c\u044b \u0433\u0440\u0443\u0441\u0442\u0438\u043c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0438\u043c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e, \u0433\u043b\u044f\u0434\u044f \u043d\u0430 \u043f\u0438\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u044c\u0442 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430. \u041a\u0441\u0442\u0430\u0442\u0438, \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043a\u0430\u043a \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u0441 \u0440\u0430\u0437\u0433\u0440\u0443\u0437\u043a\u043e\u0439 CPU.<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430.<\/p>\n<h3>Thread.Yield<\/h3>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u044e\u0434\u0435\u0439 \u0432\u044b\u0441\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.threading.thread.yield\" rel=\"noopener noreferrer nofollow\"><u>Thread.Yield<\/u><\/a> \u0432 \u0446\u0438\u043a\u043b \u0440\u0430\u0437\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c. \u0427\u0442\u043e \u0436, \u0442\u0435\u043b\u043e \u0446\u0438\u043a\u043b\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"cs\">if (stopwatch.ElapsedMilliseconds - lastTime >= intervalMs) {     callback();     lastTime = stopwatch.ElapsedMilliseconds; }  if (!Thread.Yield())     Thread.Sleep(0);<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/293\/674\/808\/29367480877cfece011812f3fb93db12.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/293\/674\/808\/29367480877cfece011812f3fb93db12.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2db\/96f\/5a8\/2db96f5a860138fce0a7c1b7d53b2afb.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2db\/96f\/5a8\/2db96f5a860138fce0a7c1b7d53b2afb.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d30\/3f9\/063\/d303f9063531b710837c50de7d6d1a86.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d30\/3f9\/063\/d303f9063531b710837c50de7d6d1a86.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0413\u0440\u0430\u0444\u0438\u043a\u0438 \u0442\u0430\u043d\u0446\u0443\u044e\u0442, \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435. \u041d\u043e \u043d\u0435\u043d\u0430\u0434\u043e\u043b\u0433\u043e, \u0438\u0431\u043e, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043b\u0443\u0447\u0448\u0435 \u043d\u0435 \u0441\u0442\u0430\u043b\u043e.<\/p>\n<h3>Thread.Sleep<\/h3>\n<p>\u0410 \u043a\u0430\u043a \u043d\u0430 \u0441\u0447\u0451\u0442 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u201c<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.threading.thread.sleep\" rel=\"noopener noreferrer nofollow\"><u>\u0441\u043d\u0430<\/u><\/a>\u201d \u043d\u0430 \u043f\u0435\u0440\u0438\u043e\u0434, \u0440\u0430\u0432\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u0430? \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>Start<\/code> \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"cs\">public void Start(int intervalMs, Action callback) {     var thread = new Thread(() =>     {         _running = true;          while (_running)         {             Thread.Sleep(intervalMs);             callback();         }     });      thread.Start(); }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/da9\/64f\/236\/da964f2367fda7f212702ea611adb880.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/da9\/64f\/236\/da964f2367fda7f212702ea611adb880.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a8d\/dce\/ce1\/a8ddcece1204015ad7649d1c62f16872.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a8d\/dce\/ce1\/a8ddcece1204015ad7649d1c62f16872.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1a7\/852\/6d1\/1a78526d17ad68405bf428bd22b4408d.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1a7\/852\/6d1\/1a78526d17ad68405bf428bd22b4408d.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0443 \u043f\u043e\u043b\u0435\u0433\u0447\u0430\u043b\u043e, \u043d\u043e \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0441\u0442\u0430\u043b\u0430 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0445\u0443\u0436\u0435. \u0421\u0440\u0435\u0434\u043d\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430\u0445 10 \u0438 100 \u043c\u0441, \u043f\u043e\u0440\u0430\u0436\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435\u043c \u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430. \u0410 \u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u0448\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u2013 \u0434\u0435\u043b\u044c\u0442\u044b \u0432 250 \u043c\u0441 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 100 \u043c\u0441 \u044d\u0442\u043e \u043d\u0435\u0445\u043e\u0440\u043e\u0448\u043e.<\/p>\n<h3>Thread.Sleep + highest priority<\/h3>\n<p>\u041d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0443 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u043e\u0432\u044b\u0448\u0435? \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u0442\u043e\u043a\u0430:<\/p>\n<pre><code class=\"cs\">{ Priority = ThreadPriority.Highest }<\/code><\/pre>\n<p>\u0413\u0440\u0430\u0444\u0438\u043a\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bd7\/599\/d22\/bd7599d22e6e794ea9b73555dc63a021.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bd7\/599\/d22\/bd7599d22e6e794ea9b73555dc63a021.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2a9\/638\/20c\/2a963820ca586cdbfcc7a070af4f6a3f.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2a9\/638\/20c\/2a963820ca586cdbfcc7a070af4f6a3f.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d1d\/482\/cf4\/d1d482cf455c6db4cb5c2271c8dcd584.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d1d\/482\/cf4\/d1d482cf455c6db4cb5c2271c8dcd584.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0412\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435.<\/p>\n<h3>nanosleep<\/h3>\n<p>\u0412\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f\u0445 \u0442\u043e, \u0447\u0442\u043e macOS \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 Unix, \u043d\u0435\u0441\u0451\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u043e, \u0447\u0442\u043e \u041e\u0421 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/en.wikipedia.org\/wiki\/POSIX\" rel=\"noopener noreferrer nofollow\"><u>POSIX<\/u><\/a>. \u042d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f. \u041b\u044e\u0431\u043e\u043f\u044b\u0442\u0441\u0442\u0432\u0430 \u0440\u0430\u0434\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0431\u0443\u0434\u0443\u0442 \u043b\u0438 \u043e\u0442\u043b\u0438\u0447\u0438\u044f \u0432 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430, \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0435 \u043d\u0430 Thread.Sleep, \u0430 \u043d\u0430 <a href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/nanosleep.2.html\" rel=\"noopener noreferrer nofollow\"><u>nanosleep<\/u><\/a>. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 C:<\/p>\n<pre><code class=\"cpp\">#include &lt;CoreFoundation\/CoreFoundation.h> #include &lt;pthread.h> #include &lt;time.h>  typedef struct {     pthread_t thread;     char active;     int intervalMs;     void (*callback)(void); } TimerInfo;  void* TimerThreadRoutine(void* data) {     TimerInfo* timerInfo = (TimerInfo*)data;     timerInfo->active = 1;      while (timerInfo->active == 1)     {         struct timespec req;         req.tv_sec = 0;         req.tv_nsec = timerInfo->intervalMs * 1000000;         nanosleep(&amp;req, NULL);                  timerInfo->callback();     }      return NULL; }  void StartTimer(int intervalMs, void (*callback)(void), TimerInfo** info) {     TimerInfo* timerInfo = malloc(sizeof(TimerInfo));     timerInfo->callback = callback;     timerInfo->intervalMs = intervalMs;      timerInfo->active = 0;     pthread_create(&amp;timerInfo->thread, NULL, TimerThreadRoutine, timerInfo);     while (timerInfo->active == 0) { }      *info = timerInfo; }  void StopTimer(TimerInfo* timerInfo) {     timerInfo->active = 0; }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e: \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0442\u043e\u043a (\u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u0438\u0432\u0435\u0442 POSIX), \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u0440\u0443\u0442\u0438\u043c \u0446\u0438\u043a\u043b \u0441 nanosleep. \u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <em>InfiniteLoopTimerWithNanosleep.dylib<\/em> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e gcc.<\/p>\n<p>\u041a\u043e\u0434 \u043d\u0430 C# \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"cs\">using System; using System.Runtime.InteropServices; using Common;  namespace InfiniteLoopTimerWithNanosleep {     internal sealed class Timer : ITimer     {         private delegate void TimerCallback();          [DllImport(\"InfiniteLoopTimerWithNanosleep.dylib\", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]         private static extern void StartTimer(int intervalMs, TimerCallback callback, out IntPtr info);          [DllImport(\"InfiniteLoopTimerWithNanosleep.dylib\", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]         private static extern void StopTimer(IntPtr info);          private IntPtr _timerInfo;         private Action _callback;         private TimerCallback _timerCallback;          public void Start(int intervalMs, Action callback)         {             _callback = callback;             _timerCallback = OnTimerTick;             StartTimer(intervalMs, _timerCallback, out _timerInfo);         }          public void Stop()         {             StopTimer(_timerInfo);         }          private void OnTimerTick()         {             _callback();         }     } }<\/code><\/pre>\n<p>\u0412\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0448 \u0442\u0430\u0439\u043c\u0435\u0440:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9cb\/c7b\/2a2\/9cbc7b2a27a386d8e8e15da6d6ac780b.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9cb\/c7b\/2a2\/9cbc7b2a27a386d8e8e15da6d6ac780b.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0dd\/656\/c85\/0dd656c8502746b8ddd57c0ca667e0de.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0dd\/656\/c85\/0dd656c8502746b8ddd57c0ca667e0de.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e7\/4d9\/582\/4e74d9582539677ee770b2529c8d2c7b.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4e7\/4d9\/582\/4e74d9582539677ee770b2529c8d2c7b.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c, \u0441\u043f\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0445\u043e\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>Thread.Sleep<\/code>, \u0445\u043e\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>nanosleep<\/code>, \u0441\u0443\u0442\u044c \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<h3>nanosleep + real-time priority<\/h3>\n<p>macOS, \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0438 Windows, \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 <a href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/Darwin\/Conceptual\/KernelProgramming\/scheduler\/scheduler.html\" rel=\"noopener noreferrer nofollow\"><u>Mach Scheduling and Thread Interfaces<\/u><\/a> \u043f\u0440\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432 \u041e\u0421, \u0432 \u0441\u0430\u043c\u043e\u043c \u0436\u0435 \u043d\u0430\u0447\u0430\u043b\u0435 \u0443\u0432\u0438\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 <em>Thread priority bands<\/em>. \u0410 \u0432 \u043d\u0435\u0439 \u0442\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443:<\/p>\n<blockquote>\n<p><em>Real-time threads | threads whose priority is based on getting a well-defined fraction of total clock cycles, regardless of other activity (in an audio player application, for example).<\/em><\/p>\n<\/blockquote>\n<p>\u0422.\u0435. macOS \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0443 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e \u0432 \u0442\u0435\u043e\u0440\u0438\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0448 \u0446\u0438\u043a\u043b \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0442\u043e\u0447\u043d\u043e. \u0418 \u0434\u0430\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u0435 \u044d\u0442\u0443 \u043d\u0430\u0445\u043e\u0434\u043a\u0443, \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043c\u043d\u0435 \u043f\u0440\u043e \u044d\u0442\u043e \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u0432 \u043c\u043e\u0451\u043c \u0436\u0435 <a href=\"https:\/\/stackoverflow.com\/questions\/57554682\/high-resolution-timer-in-macos\" rel=\"noopener noreferrer nofollow\"><u>\u0432\u043e\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 StackOverflow<\/u><\/a>.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u0434\u0430\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0433\u0443\u0441\u0442\u043e\u043c 2013-\u0433\u043e \u0433\u043e\u0434\u0430, \u043d\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0442\u0430\u043c, \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440. \u041d\u0438\u0436\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u044b \u043d\u0430\u0439\u0434\u0451\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0443 \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442:<\/p>\n<blockquote>\n<p><em>If you need real-time behavior, you must use the Mach <\/em><code>thread_policy_set<\/code><em> call. This is described in <\/em><a href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/Darwin\/Conceptual\/KernelProgramming\/scheduler\/scheduler.html#\/\/apple_ref\/doc\/uid\/TP30000905-CH211-BABHGEFA\" rel=\"noopener noreferrer nofollow\"><em><u>Using the Mach Thread API to Influence Scheduling<\/u><\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<p>\u041c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"cpp\">void SetRealtimePriority() {     mach_timebase_info_data_t timebase;     mach_timebase_info(&amp;timebase);      struct thread_time_constraint_policy constraintPolicy;      constraintPolicy.period = 1000 * 1000 * timebase.denom \/ timebase.numer;     constraintPolicy.computation = 100 * 1000 * timebase.denom \/ timebase.numer;     constraintPolicy.constraint = 500 * 1000 * timebase.denom \/ timebase.numer;     constraintPolicy.preemptible = FALSE;      thread_port_t threadId = pthread_mach_thread_np(pthread_self());     thread_policy_set(threadId, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&amp;constraintPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT); }<\/code><\/pre>\n<p>\u0421\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0437\u0434\u0435\u0441\u044c \u2013 \u043f\u043e\u043b\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b <code>thread_time_constraint_policy<\/code>. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u044f \u043d\u0430\u0448\u0451\u043b <a href=\"https:\/\/github.com\/apple\/darwin-xnu\/blob\/main\/osfmk\/mach\/thread_policy.h\" rel=\"noopener noreferrer nofollow\"><u>\u0442\u0443\u0442<\/u><\/a> (<s>\u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e, <\/s>\u043d\u0435 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Apple):<\/p>\n<blockquote>\n<p><strong><em>period<\/em><\/strong><em>: This is the nominal amount of time between separate processing arrivals, specified in absolute time units. A value of 0 indicates that there is no inherent periodicity in the computation.<\/em><\/p>\n<p><strong><em>computation<\/em><\/strong><em>: This is the nominal amount of computation time needed during a separate processing arrival, specified in absolute time units.<\/em><\/p>\n<p><strong><em>constraint<\/em><\/strong><em>: This is the maximum amount of real time that may elapse from the start of a separate processing arrival to the end of computation for logically correct functioning, specified in absolute time units. Must be (>= computation). Note that latency = (constraint &#8212; computation).<\/em><\/p>\n<\/blockquote>\n<p>\u041a\u0430\u043a \u044f \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435:<\/p>\n<blockquote>\n<p><strong><em>period<\/em><\/strong><em>: \u041f\u0435\u0440\u0438\u043e\u0434, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f (\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0430 \u0442\u0438\u043a \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435).<\/em><\/p>\n<p><strong><em>computation<\/em><\/strong><em>: \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439.<\/em><\/p>\n<p><strong><em>constraint<\/em><\/strong><em>: \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439.<\/em><\/p>\n<\/blockquote>\n<p>\u0412 \u043c\u043e\u0451\u043c \u043a\u043e\u0434\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0442\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><code>period<\/code> = 1 \u043c\u0441<\/p>\n<\/li>\n<li>\n<p><code>computation<\/code> = 0.1 \u043c\u0441<\/p>\n<\/li>\n<li>\n<p><code>constraint<\/code> = 0.5 \u043c\u0441<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u0442\u0438 \u0447\u0438\u0441\u043b\u0430 \u0432\u043f\u043e\u043b\u043d\u0435 \u0441\u043e\u0439\u0434\u0443\u0442. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u043f\u0435\u0440\u0438\u043e\u0434 \u044f \u0437\u0430\u0434\u0430\u043b \u043a\u043e\u0441\u0442\u0430\u043d\u0442\u043d\u044b\u0439 1 \u043c\u0441.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0435\u0436\u043d\u0438\u0435. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u2013 \u0432\u044b\u0437\u043e\u0432 <code>SetRealtimePriority<\/code> \u0432 <code>TimerThreadRoutine<\/code>:<\/p>\n<pre><code class=\"cpp\">void* TimerThreadRoutine(void* data) {     TimerInfo* timerInfo = (TimerInfo*)data;      SetRealtimePriority();     timerInfo->active = 1;      while (timerInfo->active == 1)     {         struct timespec req;         req.tv_sec = 0;         req.tv_nsec = timerInfo->intervalMs * 1000000;    nanosleep(&amp;req, NULL);                  timerInfo->callback();     }      return NULL; }<\/code><\/pre>\n<p>\u041a\u043e\u0434 \u043d\u0430 C# \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u043e\u043d \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 (\u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0438\u043c\u0435\u043d\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438). \u0422\u0430\u043a \u0447\u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f88\/77a\/604\/f8877a6047983de885dc72df557e88ba.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f88\/77a\/604\/f8877a6047983de885dc72df557e88ba.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a1c\/1f1\/808\/a1c1f1808eb2536e586f75f0f1c8e1c1.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a1c\/1f1\/808\/a1c1f1808eb2536e586f75f0f1c8e1c1.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/668\/197\/2db\/6681972dbc4b8b018578050331fce115.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/668\/197\/2db\/6681972dbc4b8b018578050331fce115.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0432\u043e\u0440\u0438\u0442 \u0447\u0443\u0434\u0435\u0441\u0430. \u041f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438\u0441\u043f\u044b\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443, \u043d\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e, \u0441\u043d\u0438\u0436\u0430\u044e\u0449\u0443\u044e\u0441\u044f \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u0442\u0430\u0439\u043c\u0435\u0440\u0430.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432 Windows \u0442\u0430\u043a\u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0435\u0442 (\u0438\u043b\u0438 \u044f \u043f\u043b\u043e\u0445\u043e \u0438\u0441\u043a\u0430\u043b). \u0410 \u043c\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0432 .NET \u043a\u043b\u0430\u0441\u0441\u0430\u043c \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432.<\/p>\n<h2>System.Timers.Timer<\/h2>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0442\u0430\u043a\u043e\u0439 \u043f\u0430\u0446\u0438\u0435\u043d\u0442 \u2013 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.timers.timer\" rel=\"noopener noreferrer nofollow\"><u>System.Timers.Timer<\/u><\/a>. \u041a\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cs\">using Common; using System;  namespace SystemTimersTimer {     internal sealed class Timer : ITimer     {         private System.Timers.Timer _timer;          public void Start(int intervalMs, Action callback)         {             _timer = new System.Timers.Timer(intervalMs);             _timer.Elapsed += (_, __) => callback();             _timer.Start();         }          public void Stop()         {             _timer.Stop();         }     } }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e25\/a89\/e78\/e25a89e787f41f5228cda31a4a66f040.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e25\/a89\/e78\/e25a89e787f41f5228cda31a4a66f040.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a3e\/306\/786\/a3e306786d92cad0277249f99ddee082.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a3e\/306\/786\/a3e306786d92cad0277249f99ddee082.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fc4\/dac\/0d0\/fc4dac0d03cd81486cfaa45b4fdc3d09.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fc4\/dac\/0d0\/fc4dac0d03cd81486cfaa45b4fdc3d09.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0420\u0430\u0437\u0431\u0440\u043e\u0441 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439, \u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0443 \u043e\u0442\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430. \u041e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u043f\u043b\u043e\u0445\u043e\u0439 \u0442\u0430\u0439\u043c\u0435\u0440.<\/p>\n<h2>System.Threading.Timer<\/h2>\n<p>\u0415\u0449\u0451 \u043e\u0434\u0438\u043d \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u043d\u0430 \u0437\u0432\u0430\u043d\u0438\u0435 \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u2013 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.threading.timer\" rel=\"noopener noreferrer nofollow\"><u>System.Threading.Timer<\/u><\/a>:<\/p>\n<pre><code class=\"cs\">using Common; using System;  namespace SystemThreadingTimer {     internal sealed class Timer : ITimer     {         private System.Threading.Timer _timer;          public void Start(int intervalMs, Action callback)         {             _timer = new System.Threading.Timer(_ => callback(), null, intervalMs, intervalMs);         }          public void Stop()         {             _timer.Dispose();         }     } }<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/421\/395\/de6\/421395de679445e3251314bdf112a87d.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/421\/395\/de6\/421395de679445e3251314bdf112a87d.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/10e\/3f4\/5f4\/10e3f45f4def749aefdfa0a8173aa7bf.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/10e\/3f4\/5f4\/10e3f45f4def749aefdfa0a8173aa7bf.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/551\/b2f\/d28\/551b2fd282bfdf365242b5dc202a38f3.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/551\/b2f\/d28\/551b2fd282bfdf365242b5dc202a38f3.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 <code>System.Timers.Timer<\/code>. \u041d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 1 \u043c\u0441 \u0434\u0430\u0436\u0435 \u0432\u044b\u0448\u0435 \u2013 \u0431\u043e\u043b\u0435\u0435 4%. \u0412 \u043a\u043e\u0440\u0437\u0438\u043d\u0443.<\/p>\n<h2>Run loop timer<\/h2>\n<p>\u0412 macOS \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u2013 <a href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/Cocoa\/Conceptual\/Multithreading\/RunLoopManagement\/RunLoopManagement.html\" rel=\"noopener noreferrer nofollow\"><u>run loops<\/u><\/a>. \u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e \u2013 \u044d\u0442\u043e \u0446\u0438\u043a\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u0422\u0430\u043a\u043e\u0439 \u0446\u0438\u043a\u043b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432 \u043d\u0451\u043c \u0446\u0438\u043a\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 API.<\/p>\n<p>\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 (\u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <em>When Would You Use a Run Loop?<\/em>) \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0445\u043e\u0442\u0435\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0446\u0438\u043a\u043b:<\/p>\n<blockquote>\n<p><strong><em>\u2022<\/em><\/strong><em>  Use ports or custom input sources to communicate with other threads.<br \/><\/em><strong><em>\u2022<\/em><\/strong><em>  Use timers on the thread.<br \/><\/em><strong><em>\u2022<\/em><\/strong><em>  Use any of the <\/em><code>performSelector<\/code><em>\u2026 methods in a Cocoa application.<br \/><\/em><strong><em>\u2022<\/em><\/strong><em>  Keep the thread around to perform periodic tasks.<\/em><\/p>\n<\/blockquote>\n<p>\u041d\u0430\u043c \u0442\u0443\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0435\u043d \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0443\u043d\u043a\u0442, \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0442\u0430\u0439\u043c\u0435\u0440 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u043e\u0442\u043e\u043a\u0430.<\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0446\u0438\u043a\u043b\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u044e \u043f\u043e\u0434\u0445\u043e\u0434. \u041d\u0435 \u0442\u043e \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u043d\u043e \u044d\u0442\u043e, \u0441\u0447\u0438\u0442\u0430\u044e, \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u0412 \u0434\u0438\u043a\u043e\u0439 \u043f\u0440\u0438\u0440\u043e\u0434\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043c\u0438\u0440\u0430 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u0434\u0430\u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0430\u0439\u043c\u0435\u0440 \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0442\u043e\u043a, \u043c\u044b, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0431\u0443\u0434\u0435\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u041e\u0421. \u0410 \u043f\u043e\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0435\u0443\u043c\u0438\u0440\u0430\u044e\u0449\u0438\u0439 (\u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f) \u043f\u043e\u0442\u043e\u043a, \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430 \u043d\u0451\u043c \u0442\u0430\u0439\u043c\u0435\u0440\u044b.<\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u043e\u0434 \u043d\u0430 C:<\/p>\n<pre><code class=\"cpp\">#include &lt;CoreFoundation\/CoreFoundation.h> #include &lt;pthread.h> #include &lt;mach\/mach_time.h> #include &lt;mach\/mach.h>  typedef struct {     pthread_t thread;     char active;     CFRunLoopRef runLoopRef; } TimerSessionHandle;  typedef struct {     void (*callback)(void);     CFRunLoopTimerRef timerRef; } TimerInfo;  void EmptyCallback(CFRunLoopTimerRef timer, void *info) { }  void* TimerSessionThreadRoutine(void* data) {     TimerSessionHandle* sessionHandle = (TimerSessionHandle*)data;      CFRunLoopTimerContext context = { 0, NULL, NULL, NULL, NULL };     CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(         NULL,         CFAbsoluteTimeGetCurrent() + 60,         60,         0,         0,         EmptyCallback,         &amp;context);      CFRunLoopRef runLoopRef = CFRunLoopGetCurrent();     CFRunLoopAddTimer(runLoopRef, timerRef, kCFRunLoopDefaultMode);      sessionHandle->active = 1;     sessionHandle->runLoopRef = runLoopRef;      CFRunLoopRun();     return NULL; }  void OpenTimerSession(void** handle) {     TimerSessionHandle* sessionHandle = malloc(sizeof(TimerSessionHandle));      sessionHandle->active = 0;     pthread_create(&amp;sessionHandle->thread, NULL, TimerSessionThreadRoutine, sessionHandle);     while (sessionHandle->active == 0) { }          *handle = sessionHandle; }  void TimerCallback(CFRunLoopTimerRef timer, void *info) {     TimerInfo* timerInfo = (TimerInfo*)info;     timerInfo->callback(); }  void StartTimer(int intervalMs, TimerSessionHandle* sessionHandle, void (*callback)(void), TimerInfo** info) {     TimerInfo* timerInfo = malloc(sizeof(TimerInfo));     timerInfo->callback = callback;          double seconds = (double)intervalMs \/ 1000.0;          CFRunLoopTimerContext context = { 0, timerInfo, NULL, NULL, NULL };     timerInfo->timerRef = CFRunLoopTimerCreate(         NULL,         CFAbsoluteTimeGetCurrent() + seconds,         seconds,         0,         0,         TimerCallback,         &amp;context);     CFRunLoopAddTimer(sessionHandle->runLoopRef, timerInfo->timerRef, kCFRunLoopDefaultMode);          *info = timerInfo; }  void StopTimer(TimerSessionHandle* sessionHandle, TimerInfo* timerInfo) {     CFRunLoopRemoveTimer(sessionHandle->runLoopRef, timerInfo->timerRef, kCFRunLoopDefaultMode); }<\/code><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <code>TimerSessionHandle<\/code> \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a \u0440\u0430\u0437 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u201c\u0441\u0435\u0441\u0441\u0438\u0438\u201d \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432.<\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 <code>TimerSessionThreadRoutine<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u0439\u043c\u0435\u0440 \u0441 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u043c 60 \u0441\u0435\u043a\u0443\u043d\u0434. \u0417\u0430\u0434\u0430\u0447\u0430 \u044d\u0442\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u2013 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0436\u0438\u0437\u043d\u044c \u0432 \u0446\u0438\u043a\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0446\u0438\u043a\u043b \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 (\u0430 \u0442\u0430\u0439\u043c\u0435\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0432\u044b\u043c), \u0442\u043e \u043e\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f, \u0430 \u0441 \u043d\u0438\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f \u0438 \u043d\u0430\u0448 \u043f\u043e\u0442\u043e\u043a. \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u0446\u0438\u043a\u043b, \u043d\u043e \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0442\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0446\u0438\u043a\u043b\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043f\u043e\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u0433\u043e \u0444\u0435\u0439\u043a\u043e\u0432\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <a href=\"https:\/\/developer.apple.com\/documentation\/corefoundation\/1542011-cfrunlooprun\" rel=\"noopener noreferrer nofollow\"><u>CFRunLoopRun<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b. \u0421\u0430\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u044b \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <a href=\"https:\/\/developer.apple.com\/documentation\/corefoundation\/1542132-cfrunloopaddtimer\" rel=\"noopener noreferrer nofollow\"><u>CFRunLoopAddTimer<\/u><\/a>.<\/p>\n<p>\u0412\u0440\u0435\u043c\u044f .NET:<\/p>\n<pre><code class=\"cs\">using System; using System.Runtime.InteropServices; using Common;  namespace RunLoopTimer {     internal sealed class Timer : ITimer     {         private delegate void TimerCallback();          [DllImport(\"RunLoopTimer.dylib\", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]         private static extern void OpenTimerSession(out IntPtr handle);          [DllImport(\"RunLoopTimer.dylib\", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]         private static extern void StartTimer(int intervalMs, IntPtr sessionHandle, TimerCallback callback, out IntPtr info);          [DllImport(\"RunLoopTimer.dylib\", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]         private static extern void StopTimer(IntPtr sessionHandle, IntPtr info);          private readonly IntPtr _sessionHandle;          private IntPtr _timerInfo;         private Action _callback;         private TimerCallback _timerCallback;          public Timer()         {             OpenTimerSession(out _sessionHandle);         }          public void Start(int intervalMs, Action callback)         {             _callback = callback;             _timerCallback = OnTimerTick;             StartTimer(intervalMs, _sessionHandle, _timerCallback, out _timerInfo);         }          public void Stop()         {             StopTimer(_sessionHandle, _timerInfo);         }          private void OnTimerTick()         {             _callback();         }     } }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0441\u0438\u0451 \u0447\u0443\u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0439 \u043c\u044b\u0441\u043b\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/81f\/bf1\/522\/81fbf152201753e71a0b03715898f67f.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/81f\/bf1\/522\/81fbf152201753e71a0b03715898f67f.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1f3\/24e\/3ef\/1f324e3ef58a49393f4e1779327a7745.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1f3\/24e\/3ef\/1f324e3ef58a49393f4e1779327a7745.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8ea\/dcf\/ad0\/8eadcfad094cfc39a10b98bfce27742b.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8ea\/dcf\/ad0\/8eadcfad094cfc39a10b98bfce27742b.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0421\u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u0430\u043b\u0438 \u043d\u0430\u043c \u043d\u0435 \u0442\u0430\u043a\u0438\u0435 \u0443\u0436 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b. \u0413\u0440\u0430\u0444\u0438\u043a\u0438 \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043b\u0443\u0447\u0448\u0435 \u0442\u0435\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0432\u0438\u0434\u0435\u043b\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u043d\u0430 \u0446\u0438\u043a\u043b\u0430\u0445 \u0441\u043e \u0441\u043d\u043e\u043c.<\/p>\n<h3>Real-time priority<\/h3>\n<p>\u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f. \u041f\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u043c \u043d\u0430\u0448 \u043f\u043e\u0442\u043e\u043a \u0432 \u0440\u0435\u0436\u0438\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043a\u0430\u043a \u043c\u044b \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0434\u043b\u044f nanosleep. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>TimerSessionThreadRoutine<\/code> \u0432\u044b\u0437\u043e\u0432 <code>SetRealtimePriority<\/code> \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0435\u0439\u043a\u043e\u0432\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cpp\">CFRunLoopAddTimer(runLoopRef, timerRef, kCFRunLoopDefaultMode); SetRealtimePriority();<\/code><\/pre>\n<p>\u041a\u043e\u0434 \u043d\u0430 C#, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0442\u043e\u0442 \u0436\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/367\/d6e\/bf0\/367d6ebf0e05a5a2983b2b07f78d955e.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/367\/d6e\/bf0\/367d6ebf0e05a5a2983b2b07f78d955e.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c94\/1ca\/4f5\/c941ca4f59369c35c8f051a94ef372de.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c94\/1ca\/4f5\/c941ca4f59369c35c8f051a94ef372de.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c60\/298\/6bb\/c602986bb3137f39f4ef9f715639ee9e.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c60\/298\/6bb\/c602986bb3137f39f4ef9f715639ee9e.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0413\u043b\u0430\u0437 \u0440\u0430\u0434\u0443\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c \u043a\u0430\u0440\u0442\u0438\u043d\u0430\u043c. \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0441\u043d\u043e\u0432\u0430 \u0432\u044b\u0440\u0443\u0447\u0438\u043b \u043d\u0430\u0441. \u0418 \u0445\u043e\u0442\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0434\u043b\u044f nanosleep \u0441 \u0442\u0435\u043c \u0436\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0430, \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u0446\u0438\u043a\u043b\u0430\u043c\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u043d\u0435 \u0432\u0438\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u0435\u0435 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u2013 \u0442\u0443\u0442 \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u0430\u043c\u0438. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u0442\u0430\u043a\u0438\u0435 \u0432\u0435\u0449\u0438:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u0432 \u0435\u0434\u0438\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u043d\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0410 \u0435\u0441\u043b\u0438 \u0432\u0441\u0451 \u044d\u0442\u043e \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445, \u043d\u0435 \u043b\u0443\u0447\u0448\u0435 \u043b\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043c\u0438?<\/p>\n<h3>Tolerance<\/h3>\n<p>\u0415\u0441\u0442\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440. \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 <a href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/Performance\/Conceptual\/EnergyGuide-iOS\/MinimizeTimerUse.html\" rel=\"noopener noreferrer nofollow\"><u>Minimize Timer Use<\/u><\/a> \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u0443\u0441\u043a (tolerance) \u0434\u043b\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432:<\/p>\n<blockquote>\n<p><em>Specify a tolerance for the accuracy of when your timers fire. The system will use this flexibility to shift the execution of timers by small amounts of time\u2014within their tolerances\u2014so that multiple timers can be executed at the same time. Using this approach dramatically increases the amount of time that the processor spends idling while users detect no change in system responsiveness.<\/em><\/p>\n<\/blockquote>\n<p>\u041d\u0443\u0436\u043d\u043e \u044d\u0442\u043e, \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0437 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0448\u0435 \u0430\u0431\u0437\u0430\u0446\u0430, \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0439 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432, \u043a \u0441\u043b\u043e\u0432\u0443, \u0435\u0441\u0442\u044c \u0438 \u0432 Windows (\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 <a href=\"http:\/\/download.microsoft.com\/download\/3\/0\/2\/3027d574-c433-412a-a8b6-5e0a75d5b237\/timer-resolution.docx\" rel=\"noopener noreferrer nofollow\"><u>Timers, Timer Resolution, and Development of Efficient Code<\/u><\/a>, \u0440\u0430\u0437\u0434\u0435\u043b <em>Timer Coalescing<\/em>). \u041f\u0440\u0438\u0447\u0451\u043c \u0437\u0430\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0442\u0430\u0439\u043c\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 <code>[i, i+t]<\/code>, \u0433\u0434\u0435 <code>i<\/code> \u2013 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b, \u0430 <code>t<\/code> \u2013 \u0434\u043e\u043f\u0443\u0441\u043a:<\/p>\n<blockquote>\n<p><em>After you specify a tolerance for a timer, it may fire anytime between its scheduled fire date and the scheduled fire date, plus the tolerance.<\/em><\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u043d\u0430 \u0446\u0438\u043a\u043b\u0430\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 (run loops) \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <a href=\"https:\/\/developer.apple.com\/documentation\/corefoundation\/1542980-cfrunlooptimersettolerance\" rel=\"noopener noreferrer nofollow\"><u>CFRunLoopTimerSetTolerance<\/u><\/a>. \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043e\u0442 Apple, \u043a\u0430\u043a \u044f \u0443\u0436\u0435 \u043f\u043e\u0434\u043c\u0435\u0447\u0430\u043b \u0432 \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/570670\/\" rel=\"noopener noreferrer nofollow\"><u>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 CoreMIDI<\/u><\/a>, \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u0442\u0430\u043a\u043e\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c, \u0430 \u043f\u043e\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>StartTimer<\/code> \u0432\u044b\u0437\u043e\u0432 <code>CFRunLoopTimerSetTolerance<\/code> \u043f\u0435\u0440\u0435\u0434 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0442\u0430\u0439\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cpp\">CFRunLoopTimerSetTolerance(timerInfo->timerRef, 0.001); CFRunLoopAddTimer(sessionHandle->runLoopRef, timerInfo->timerRef, kCFRunLoopDefaultMode);<\/code><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>0.001<\/code> \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043e\u043f\u0443\u0441\u043a \u0440\u0430\u0432\u0435\u043d 1 \u043c\u0441. \u041a\u043e\u0434 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u043d\u0430 .NET \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4d1\/bc5\/293\/4d1bc52939aaa4f048bcd6155b9df981.png\" alt=\"1 \u043c\u0441\" title=\"1 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4d1\/bc5\/293\/4d1bc52939aaa4f048bcd6155b9df981.png\"\/><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/229\/b30\/7ed\/229b307ed2895f8bda2b584a20aea544.png\" alt=\"10 \u043c\u0441\" title=\"10 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/229\/b30\/7ed\/229b307ed2895f8bda2b584a20aea544.png\"\/><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/135\/26d\/00c\/13526d00cc0b28fe49bfeb44e113eafb.png\" alt=\"100 \u043c\u0441\" title=\"100 \u043c\u0441\" width=\"1500\" height=\"750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/135\/26d\/00c\/13526d00cc0b28fe49bfeb44e113eafb.png\"\/><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0443 \u0441\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u043e. \u0421\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u043f\u043e\u0445\u043e\u0436\u0435, \u0447\u0442\u043e \u0442\u0430\u0439\u043c\u0435\u0440 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0434\u043e\u043f\u0443\u0441\u043a\u0430. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043f\u043e\u0434\u0441\u043a\u043e\u0447\u0438\u043b\u0430, \u0430 \u0434\u043e\u043f\u0443\u0441\u043a \u0437\u0430\u0442\u0435\u0432\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0430. \u041c\u0435\u043d\u044f \u043d\u0435 \u043f\u043e\u043a\u0438\u0434\u0430\u044e\u0442 \u043c\u044b\u0441\u043b\u0438, \u0447\u0442\u043e \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0433\u043b\u0443\u043f\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u043d\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e, \u0433\u0434\u0435. \u041d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043c\u044b \u0434\u043e\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0442\u0430\u0439\u043c\u0435\u0440, \u0442\u0430\u043a \u0447\u0442\u043e \u0443 \u043f\u043e\u0442\u043e\u043a\u0430 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>\u041f\u043e \u044d\u0442\u0438\u043c \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0442\u0430\u0439\u043c\u0435\u0440 \u0441\u0442\u0430\u043b \u043d\u0435\u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u043c \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439, \u0442\u0430\u043a \u0447\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0434\u043e\u043f\u0443\u0441\u043a\u0430 \u044f \u0432 \u0441\u0432\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043d\u0435 \u0434\u0435\u043b\u0430\u043b.<\/p>\n<h2>\u0418\u0442\u043e\u0433\u0438<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e: \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e\u0447\u043d\u044b\u0439 \u0442\u0430\u0439\u043c\u0435\u0440 \u0432 macOS \u043d\u0430 .NET \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0421\u0442\u043e\u0438\u0442, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0437\u044f\u0442\u044c \u0432 \u043a\u0430\u0432\u044b\u0447\u043a\u0438 .NET, \u0438\u0431\u043e, \u043a\u0430\u043a \u0438 \u0432 Windows, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438. \u041d\u043e \u0446\u0435\u043b\u044c \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u0430.<\/p>\n<p>\u0412 \u0441\u0432\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0446\u0438\u043a\u043b\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 (run loops) \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432. \u0415\u0441\u043b\u0438 \u043a\u043e\u043c\u0443-\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c \u043d\u0430\u0434 \u043d\u0438\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>\u0417\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044e, \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0437\u0430\u0434\u0430\u0442\u044c \u0431\u0435\u0437\u043e\u0442\u0432\u0435\u0442\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441: \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e\u0447\u043d\u044b\u0439 \u0442\u0430\u0439\u043c\u0435\u0440 \u0447\u0442\u043e \u0432 Windows, \u0447\u0442\u043e \u0432 macOS (\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0438 \u0432 *nix), \u043f\u043e\u0447\u0435\u043c\u0443 .NET \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e? \u0423\u0432\u0435\u0440\u0435\u043d, \u0447\u0442\u043e \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b Microsoft \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 API, \u0438 \u0435\u0441\u0442\u044c \u0443\u0432\u0430\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 BCL. \u041d\u043e \u043e\u0442 \u043c\u0435\u043d\u044f \u044d\u0442\u0430 \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0443\u0441\u043a\u043e\u043b\u044c\u0437\u0430\u0435\u0442.<\/p>\n<p>\u0412\u0441\u0435\u043c \u0441\u043f\u0430\u0441\u0438\u0431\u043e. \u041a\u0430\u043a \u0438 \u043e\u0431\u0435\u0449\u0430\u043b, \u043f\u0440\u0438\u0432\u043e\u0436\u0443 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.dropbox.com\/s\/zm59zk4u3zomttt\/MacTimers.zip?dl=0\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u043e\u0434 \u0441\u043e\u043b\u044e\u0448\u043d\u0430 \u0441 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u043a\u043e\u0434\u043e\u043c<\/u><\/a>;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.dropbox.com\/s\/xslriars6l9v4ei\/Native.zip?dl=0\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u043e\u0434 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a<\/u><\/a>;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d Azure Pipelines:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.dropbox.com\/s\/5xywo4f36l4ol3v\/Deltas_AzurePipelines.zip?dl=0\" rel=\"noopener noreferrer nofollow\"><u>\u0434\u0435\u043b\u044c\u0442\u044b<\/u><\/a>;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.dropbox.com\/s\/nsvj77c4q2oxjc3\/CPU_AzurePipelines.zip?dl=0\" rel=\"noopener noreferrer nofollow\"><u>CPU<\/u><\/a>;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.dropbox.com\/s\/4or7bf2b2q6wi4f\/Graphs_Merged_AzurePipelines.zip?dl=0\" rel=\"noopener noreferrer nofollow\"><u>\u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c \u0441 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d Azure Pipelines<\/u><\/a>;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.dropbox.com\/s\/pwqsu0rjyll0nuo\/DwmGraph.zip?dl=0\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u043e\u0434 \u0441\u043e\u043b\u044e\u0448\u043d\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432<\/u><\/a>.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/654581\/\"> https:\/\/habr.com\/ru\/post\/654581\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0439, \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0443\u0436\u0435\u043d \u0442\u0430\u0439\u043c\u0435\u0440 \u0441 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u043c 1 \u043c\u0441. \u0412 \u0441\u0432\u043e\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/github.com\/melanchall\/drywetmidi\" rel=\"noopener noreferrer nofollow\"><u>DryWetMIDI<\/u><\/a> \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0442\u0430\u0439\u043c\u0435\u0440 \u0432 \u0440\u043e\u043b\u0438 \u201c\u0434\u0432\u0438\u0433\u0430\u0442\u0435\u043b\u044f\u201d \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f MIDI-\u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u043e \u0432\u0441\u0442\u0443\u043f\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/650021\/\" rel=\"noopener noreferrer nofollow\"><u>\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/u><\/a>. \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043b\u044f Windows \u0438 macOS. \u0421\u0442\u0430\u0442\u044c\u044e \u043f\u043e *nix, \u0443\u0432\u044b, \u0436\u0434\u0430\u0442\u044c \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435 \u0441\u0442\u043e\u0438\u0442.<\/p>\n<p>\u041a \u0441\u043b\u043e\u0432\u0443, \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u0438\u0441\u0430\u043b \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u043f\u043b\u0435\u0435\u0440\u044b \u043f\u043e\u0432\u044b\u0448\u0430\u044e\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430, \u0430 \u044d\u0442\u043e \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443\u0435\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043c\u043e\u0435\u043c\u0443 \u043f\u043e\u0434\u0445\u043e\u0434 \u0441 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u043c \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 (\u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u0432\u0435\u0441\u044c\u043c\u0430 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e), \u0447\u0442\u043e \u044f \u0434\u0435\u043b\u0430\u044e \u043b\u043e\u0436\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u044d\u0442\u0438\u043c\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430\u043c\u0438, \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u2013 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0443 \u0431\u0443\u0444\u0435\u0440 \u0438 \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0430 \u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u0430. \u042f <a href=\"https:\/\/forum.videolan.org\/viewtopic.php?f=2&amp;t=159238\" rel=\"noopener noreferrer nofollow\"><u>\u043d\u0430\u043f\u0438\u0441\u0430\u043b<\/u><\/a> \u043d\u0430 \u0444\u043e\u0440\u0443\u043c VLC, \u0434\u0430\u0431\u044b \u0443\u0442\u043e\u0447\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u0432 \u044d\u0442\u043e\u043c \u043f\u043b\u0435\u0435\u0440\u0435 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e. \u0412\u043e\u0442 \u043e\u0442\u0432\u0435\u0442:<\/p>\n<blockquote>\n<p><em>VLC 3.0 currently compare the media time against a media clock whose parameters are generated from the media timing information. When the clock says that the media time associated with a frame has been reached, it renders the frame. So in a sense, it&#8217;s &#171;like&#187; timers yes, and not tickless or event-driven.<\/em><\/p>\n<\/blockquote>\n<p>\u0422.\u0435. \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c VLC \u0432\u0441\u0451 \u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u201c\u0442\u0430\u0439\u043c\u0435\u0440\u043e\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439\u201d \u043f\u043e\u0434\u0445\u043e\u0434.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0441\u044c \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c macOS, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0431\u044b\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043d\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445 <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/pipelines\/agents\/hosted?view=azure-devops\" rel=\"noopener noreferrer nofollow\"><u>Azure Pipelines \u043f\u0443\u043b\u0430 Microsoft<\/u><\/a>, \u0432\u0435\u0440\u0441\u0438\u044f \u041e\u0421 11.0.0. \u0414\u0430, \u044d\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0447\u0435\u0441\u0442\u043d\u043e, \u043d\u043e \u0447\u0442\u043e \u043f\u043e\u0434\u0435\u043b\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u0443 \u043a\u043e\u0433\u043e-\u0442\u043e \u0435\u0441\u0442\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0438 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0436\u0435\u043b\u0435\u0437\u0435, \u044f \u0431\u044b\u043b \u0431\u044b \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u043e, \u0431\u044b\u043b\u0438 \u0431\u044b \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430\u043c\u0438 Intel \u0438 Apple.<\/p>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/h2>\n<p>\u0414\u0430\u0431\u044b \u0441\u0442\u0430\u0442\u044c\u044f \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0431\u044b\u043b\u0430 \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0439 \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u044b\u0433\u0430\u0442\u044c \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439, \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0435\u0449\u0451 \u0440\u0430\u0437 \u043a\u043e\u0434 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u044f.<\/p>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"cs\">using System;  namespace Common {     public interface ITimer     {         void Start(int intervalMs, Action callback);         void Stop();     } }<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u043a\u043e\u0434 \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u0440\u0430 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0441\u0442\u0430\u043b \u0447\u0443\u0442\u044c \u0434\u043b\u0438\u043d\u043d\u0435\u0435. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u044f \u043d\u0435 \u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043b\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u043d\u044f\u0442\u0438\u0435\u043c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u0443\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u0442\u044c\u0438. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 CPU \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0442\u0430\u0439\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"cs\">using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading;  namespace Common {     public static class TimerChecker     {         private static readonly TimeSpan MeasurementDuration = TimeSpan.FromMinutes(3);         private static readonly TimeSpan CpuMeasurementInterval = TimeSpan.FromMilliseconds(500);         private static readonly int[] IntervalsToCheck = { 1, 10, 100 };          public static void Check(ITimer timer)         {             Console.WriteLine(\"Starting measuring...\");             Console.WriteLine($\"OS: {Environment.OSVersion}\");             Console.WriteLine($\"CPUs: {Environment.ProcessorCount}\");             Console.WriteLine(\"--------------------------------\");              foreach (var intervalMs in IntervalsToCheck)             {                 Console.WriteLine($\"Measuring interval of {intervalMs} ms...\");                 CheckInterval(timer, intervalMs);             }              Console.WriteLine(\"All done.\");         }          private static void CheckInterval(ITimer timer, int intervalMs)         {             var times = new List&lt;long>((int)Math.Ceiling(MeasurementDuration.TotalMilliseconds));             var cpuUsage = new List&lt;float>((int)Math.Ceiling(MeasurementDuration.TotalMilliseconds \/ CpuMeasurementInterval.TotalMilliseconds));                          var stopwatch = new Stopwatch();                          var cpuTimer = new System.Timers.Timer(CpuMeasurementInterval.TotalMilliseconds);             var cpuStep = 0;              var cpuUsageStopwatch = new Stopwatch();             var startCpuUsage = TimeSpan.Zero;             var startTime = 0L;              cpuTimer.Elapsed += (_, _) =>             {                 if (cpuStep++ > 0)                 {                     var cpuUsedMs = (float)(Process.GetCurrentProcess().TotalProcessorTime - startCpuUsage).TotalMilliseconds;                     var totalMsPassed = cpuUsageStopwatch.ElapsedMilliseconds - startTime;                     var cpuUsageTotal = cpuUsedMs \/ totalMsPassed;                     cpuUsage.Add(cpuUsageTotal * 100);                 }                  startTime = cpuUsageStopwatch.ElapsedMilliseconds;                 startCpuUsage = Process.GetCurrentProcess().TotalProcessorTime;              };                          Action callback = () => times.Add(stopwatch.ElapsedMilliseconds);              timer.Start(intervalMs, callback);             stopwatch.Start();             cpuTimer.Start();             cpuUsageStopwatch.Start();              Thread.Sleep(MeasurementDuration);              timer.Stop();             stopwatch.Stop();             cpuTimer.Stop();                          File.WriteAllLines($\"cpu_{intervalMs}.txt\", cpuUsage.ToArray().Select(u => u.ToString(\"0.##\")));              var deltas = new List&lt;long>();             var lastTime = 0L;              foreach (var time in times.ToArray())             {                 var delta = time - lastTime;                 deltas.Add(delta);                 lastTime = time;             }              File.WriteAllLines($\"deltas_{intervalMs}.txt\", deltas.Select(d => d.ToString()));         }     } }<\/code><\/pre>\n<p>\u0422.\u0435. \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0441\u043d\u0438\u043c\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0435 500 \u043c\u0441 (\u0447\u0435\u0433\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e) \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u0418 \u0434\u0430\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043c\u043d\u043e\u0433\u043e\u044f\u0434\u0435\u0440\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u044f\u0434\u0440\u0443. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443, \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0431\u044b\u043b \u043e\u0434\u043d\u043e\u044f\u0434\u0435\u0440\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 100%, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u044f\u0434\u0440\u0430, \u0430 \u043d\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u0420\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0431\u044b\u043b\u0430 \u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.environment.processorcount\" rel=\"noopener noreferrer nofollow\"><u>Environment.ProcessorCount<\/u><\/a>.<\/p>\n<p>\u041a\u0430\u043a \u0438 \u0440\u0430\u043d\u044c\u0448\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 3 \u043c\u0438\u043d\u0443\u0442 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 1, 10 \u0438 100 \u043c\u0441. \u0413\u0440\u0430\u0444\u0438\u043a\u0438 \u0434\u0435\u043b\u044c\u0442 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 CPU:<\/p>\n<figure class=\"full-width\"><figcaption>\u0422\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/figcaption><\/figure>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043a\u043e\u0434, \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0432 \u043a\u043e\u043d\u0446\u0435.<\/p>\n<h2>\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b<\/h2>\n<p>\u0418 \u0441\u043d\u043e\u0432\u0430 \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u043d\u0435\u0441\u0442\u0430\u0440\u0435\u044e\u0449\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u043a\u0438 \u2013 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b:<\/p>\n<pre><code class=\"cs\">using Common; using System; using System.Diagnostics; using System.Threading;  namespace InfiniteLoopTimer {     internal sealed class Timer : ITimer     {         private bool _running;          public void Start(int intervalMs, Action callback)         {             var thread = new Thread(() =>             {                 var lastTime = 0L;                 var stopwatch = new Stopwatch();                  _running = true;                 stopwatch.Start();                  while (_running)                 {                     if (stopwatch.ElapsedMilliseconds - lastTime &lt; intervalMs)                         continue;                      callback();                     lastTime = stopwatch.ElapsedMilliseconds;                 }             });              thread.Start();         }          public void Stop()         {             _running = false;         }     } }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u0430, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0430\u043a\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0422\u0430\u0439\u043c\u0435\u0440 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u0442\u043e\u0447\u043d\u044b\u0439. \u0418 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043f\u043b\u043e\u0445\u043e\u0439, \u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043f\u0440\u0435\u0431\u044b\u0432\u0430\u0435\u0442 \u0432 \u0433\u0440\u0443\u0441\u0442\u0438 \u043e\u0442 \u0434\u0430\u043d\u043d\u043e\u0439 \u0435\u043c\u0443 \u0437\u0430\u0434\u0430\u0447\u0438. \u0410 \u043c\u044b \u0433\u0440\u0443\u0441\u0442\u0438\u043c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0438\u043c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e, \u0433\u043b\u044f\u0434\u044f \u043d\u0430 \u043f\u0438\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u044c\u0442 \u043c\u0435\u0436\u0434\u0443 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430. \u041a\u0441\u0442\u0430\u0442\u0438, \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043a\u0430\u043a \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u0441 \u0440\u0430\u0437\u0433\u0440\u0443\u0437\u043a\u043e\u0439 CPU.<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0430.<\/p>\n<h3>Thread.Yield<\/h3>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u044e\u0434\u0435\u0439 \u0432\u044b\u0441\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.threading.thread.yield\" rel=\"noopener noreferrer nofollow\"><u>Thread.Yield<\/u><\/a> \u0432 \u0446\u0438\u043a\u043b \u0440\u0430\u0437\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c. \u0427\u0442\u043e \u0436, \u0442\u0435\u043b\u043e \u0446\u0438\u043a\u043b\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"cs\">if (stopwatch.ElapsedMilliseconds - lastTime >= intervalMs) {     callback();     lastTime = stopwatch.ElapsedMilliseconds; }  if (!Thread.Yield())     Thread.Sleep(0);<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<figure class=\"full-width\"><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0413\u0440\u0430\u0444\u0438\u043a\u0438 \u0442\u0430\u043d\u0446\u0443\u044e\u0442, \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435. \u041d\u043e \u043d\u0435\u043d\u0430\u0434\u043e\u043b\u0433\u043e, \u0438\u0431\u043e, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043b\u0443\u0447\u0448\u0435 \u043d\u0435 \u0441\u0442\u0430\u043b\u043e.<\/p>\n<h3>Thread.Sleep<\/h3>\n<p>\u0410 \u043a\u0430\u043a \u043d\u0430 \u0441\u0447\u0451\u0442 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u201c<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.threading.thread.sleep\" rel=\"noopener noreferrer nofollow\"><u>\u0441\u043d\u0430<\/u><\/a>\u201d \u043d\u0430 \u043f\u0435\u0440\u0438\u043e\u0434, \u0440\u0430\u0432\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0443 \u0442\u0430\u0439\u043c\u0435\u0440\u0430? \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>Start<\/code> \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"cs\">public void Start(int intervalMs, Action callback) {     var thread = new Thread(() =>     {         _running = true;          while (_running)         {             Thread.Sleep(intervalMs);             callback();         }     });      thread.Start(); }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<figure class=\"full-width\"><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0443 \u043f\u043e\u043b\u0435\u0433\u0447\u0430\u043b\u043e, \u043d\u043e \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0441\u0442\u0430\u043b\u0430 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0445\u0443\u0436\u0435. \u0421\u0440\u0435\u0434\u043d\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430\u0445 10 \u0438 100 \u043c\u0441, \u043f\u043e\u0440\u0430\u0436\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435\u043c \u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430. \u0410 \u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u0448\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u2013 \u0434\u0435\u043b\u044c\u0442\u044b \u0432 250 \u043c\u0441 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 100 \u043c\u0441 \u044d\u0442\u043e \u043d\u0435\u0445\u043e\u0440\u043e\u0448\u043e.<\/p>\n<h3>Thread.Sleep + highest priority<\/h3>\n<p>\u041d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0443 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u043e\u0432\u044b\u0448\u0435? \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u0442\u043e\u043a\u0430:<\/p>\n<pre><code class=\"cs\">{ Priority = ThreadPriority.Highest }<\/code><\/pre>\n<p>\u0413\u0440\u0430\u0444\u0438\u043a\u0438:<\/p>\n<figure class=\"full-width\"><figcaption>1 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>10 \u043c\u0441<\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption>100 \u043c\u0441<\/figcaption><\/figure>\n<p>\u0412\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435.<\/p>\n<h3>nanosleep<\/h3>\n<p>\u0412\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f\u0445 \u0442\u043e, \u0447\u0442\u043e macOS \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 Unix, \u043d\u0435\u0441\u0451\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u043e, \u0447\u0442\u043e \u041e\u0421 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/en.wikipedia.org\/wiki\/POSIX\" rel=\"noopener noreferrer nofollow\"><u>POSIX<\/u><\/a>. \u042d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f. \u041b\u044e\u0431\u043e\u043f\u044b\u0442\u0441\u0442\u0432\u0430 \u0440\u0430\u0434\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0431\u0443\u0434\u0443\u0442 \u043b\u0438 \u043e\u0442\u043b\u0438\u0447\u0438\u044f \u0432 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430, \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0435 \u043d\u0430 Thread.Sleep, \u0430 \u043d\u0430 <a href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/nanosleep.2.html\" rel=\"noopener noreferrer nofollow\"><u>nanosleep<\/u><\/a>. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 C:<\/p>\n<pre><code class=\"cpp\">#include &lt;CoreFoundation\/CoreFoundation.h> #include &lt;pthread.h> #include &lt;time.h>  typedef struct {     pthread_t thread;     char active;     int intervalMs;     void (*callback)(void); } TimerInfo;  void* TimerThreadRoutine(void* data) {     TimerInfo* timerInfo = (TimerInfo*)data;     timerInfo->active = 1;      while (timerInfo->active == 1)     {         struct timespec req;         req.tv_sec = 0;         req.tv_nsec = timerInfo->intervalMs * 1000000;         nanosleep(&amp;req,<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-330366","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330366","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=330366"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330366\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330366"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330366"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}