【问题标题】:Replace code with timer as opposed to thread sleep用计时器代替代码而不是线程睡眠
【发布时间】:2015-02-10 10:25:39
【问题描述】:

根据这个Stack Overflow discussion,使用Thread.Sleep() 几乎总是一个坏主意。我将如何重构我的代码以使用计时器。我尝试通过执行以下操作来开始:

namespace Engine
{
    internal class Program
    {
        public static DbConnect DbObject = new DbConnect();

        System.Timers.Timer timer = new System.Timers.Timer();

        // error here
        timer.Interval = 2000;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        timer.Enabled=false;
    }
}

但不断收到cannot resolve symbol 错误消息。

namespace Engine
{
    internal class Program
    {
    public static DbConnect DbObject = new DbConnect();
    private static void Main()
    {
        SettingsComponent.LoadSettings();

        while (true)
        {
            try
            {
                for (int x = 0; x < 4; x++)
                {
                    GenerateRandomBooking(); 
                }
                Thread.Sleep(2000); 
                GenerateRandomBids();
                AllocateBids();
                Thread.Sleep(2000); 
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
    }
}

【问题讨论】:

  • 你必须把你的定时器初始化放到一个方法中,例如在 Main 的开头。

标签: c# multithreading timer


【解决方案1】:

如果您使用的是 .Net 4.5 或更高版本,则可以使用 await 代替 Timer。

例如:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    public static class Program
    {
        private static void Main()
        {
            Console.WriteLine("Generating bids for 30 seconds...");

            using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = GenerateBids(cancellationTokenSource.Token);

                // You can do other work here as required.

                task.Wait();
            }

            Console.WriteLine("\nTask finished.");
        }

        private static async Task GenerateBids(CancellationToken cancel)
        {
            while (!cancel.IsCancellationRequested)
            {
                Console.WriteLine("");

                try
                {
                    for (int x = 0; x < 4; x++)
                        GenerateRandomBooking();

                    await Task.Delay(2000);

                    if (cancel.IsCancellationRequested)
                        return;

                    GenerateRandomBids();
                    AllocateBids();

                    await Task.Delay(2000);
                }

                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }

        private static void AllocateBids()
        {
            Console.WriteLine("AllocateBids()");
        }

        private static void GenerateRandomBids()
        {
            Console.WriteLine("GenerateRandomBids()");
        }

        private static void GenerateRandomBooking()
        {
            Console.WriteLine("GenerateRandomBooking()");
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以在不使用 Thread.Sleep() 的情况下转换您的代码

    private static void Main()
        {
            SettingsComponent.LoadSettings();
    
            //while (true)
            {
                try
                {
                    RaiseRandomBooking(null);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
    
        static void RaiseRandomBooking(object state)
        {
            for (int x = 0; x < 4; x++)
            {
                GenerateRandomBooking();
            }
            System.Threading.Timer tmr = new System.Threading.Timer(RaiseRandomBids, null, 0, 2000);
        }
    
        static void RaiseRandomBids(object state)
        {
            GenerateRandomBids();
            AllocateBids();
            System.Threading.Timer tmr = new System.Threading.Timer(RaiseRandomBooking, null, 0, 2000);
        }
    

    【讨论】:

    • RaiseRandomBooking 中的 for 循环后代码不会退出吗?因为在此之后没有任何东西阻塞主线程中的执行
    • @BoeseB,RaiseRandomBooking() 方法执行将退出,但计时器委托正在后台运行。
    • 所以 MainThread 会运行到结束并且控制台会在委托执行之前关闭?所以整个应用程序都被杀死了,还是我弄错了?
    猜你喜欢
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多