是thread.sleep在.NET Core 2.0控制台应用程序中要做的正确的事情



通常我避免使用Thread.Sleep,除了测试或调试代码外,

在下面的示例中,我正在尝试运行一个控制台应用程序,该应用程序将运行不同的类,这些类别将在某些时间触发计时器滴答。这个想法是添加更多运行独立服务的类。

目前我正在使用的是,Thread.Sleep(10000);只是为了保持控制台打开以允许代码运行。

肯定是Thread.Sleep阻止了CPU的一些重新解析吗?

有更好的方法吗?(这是针对Windows和Linux的)

while(true)
{
   Thread.Sleep(10000);
}

程序:

class Program
{
    private static CultureInfo culture = new CultureInfo("en-gb");
    static void Main(string[] args)
    {
        LongRunningClass longRunningClass = new LongRunningClass();
        while(true)
        {
            Thread.Sleep(10000);
        }
    }
}

长期运行任务:

public class LongRunningClass
{
    private Timer timer;
    private List<TimeSpan> ScheduleTimes = new List<TimeSpan>()
    {
        new TimeSpan(4,0,0),
        new TimeSpan(6,0,0),
        new TimeSpan(21,0,0),
        new TimeSpan(23,0,0),
    };
    public LongRunningClass()
    {            
        this.timer = new Timer(1000);
        this.timer.Elapsed += new ElapsedEventHandler(OnTick);
        this.timer.Start();
    }
    protected virtual void OnTick(object sender, ElapsedEventArgs e)
    {
        this.timer.Stop();
        RunLongRunningTask();
        double nextTickInterval = 0;
        TimeSpan timeOfDayNow = DateTime.Now.TimeOfDay;
        foreach (TimeSpan scheduleTime in ScheduleTimes)
        {
            if (scheduleTime > timeOfDayNow)
            {
                nextTickInterval = (scheduleTime - timeOfDayNow).TotalMilliseconds;
                break;
            }
        }
        // If tick interval not set yet then restart for next day
        if (nextTickInterval <= 0)
        {
            TimeSpan scheduleTime = ScheduleTimes[0].Add(new TimeSpan(1, 0, 0, 0));
            nextTickInterval = (scheduleTime - timeOfDayNow).TotalMilliseconds;
        }
        this.timer.Interval = nextTickInterval;

        this.timer.Start();
    }
    private void RunLongRunningTask()
    {
        // Long Running Task
    }
}

如果是要保持控制台打开。你尝试过吗?

while(true)
{
   Console.Read();
}

或仅:

Console.Read();

所以,除非您按键,否则它不会关闭。

您可以无限期地保持控制台打开,直到使用Autoresetevent取消用户:

class Program
{
    private static AutoResetEvent autoResetEvent;
    private static CultureInfo culture = new CultureInfo("en-gb");
    static void Main(string[] args)
    {
        LongRunningClass longRunningClass = new LongRunningClass();
        WaitForCancel();
    }
    /// <summary>
    /// When cancel keys Ctrl+C or Ctrl+Break are used, set the event.
    /// </summary>
    private static void WaitForCancel()
    {
        autoResetEvent = new AutoResetEvent(false);
        Console.WriteLine("Press CTRL + C or CTRL + Break to exit...");
        Console.CancelKeyPress += (sender, e) =>
            {
                e.Cancel = true;
                autoResetEvent.Set();
            };
        autoResetEvent.WaitOne();
    }
}

显然,此方法依靠您知道线程何时完成处理。

肯定是线程。

它不是您必须担心的CPU,而是它的内存。您可以在此处读取复杂的版本,但是简单的版本是每个线程使用1MB的内存用于堆栈。如果您正在编写需要很多线程的应用程序,则应考虑编写异步方法并使用Task.Delay。这允许线程在方法等待时做其他事情,这可以减少处理相同工作量所需的线程总数。

在这种情况下,

没有太大的意义 - 虽然C#7.1确实支持异步主体,但它只是句法糖,并且不会释放线程以执行其他工作。在任何情况下,我都不会在这样的简单控制台应用中使用Thread.Sleep,或者使用诸如NEOS07之类的Console.ReadLine建议。

Thread.Sleep仍然有效,但是您可以考虑在此处使用Task.Delay作为替代方案,例如

await Task.Delay(1000);

相关内容

最新更新