Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#每秒运行一个函数的最佳方式,计时器还是线程?_C#_Multithreading_Timer - Fatal编程技术网

C#每秒运行一个函数的最佳方式,计时器还是线程?

C#每秒运行一个函数的最佳方式,计时器还是线程?,c#,multithreading,timer,C#,Multithreading,Timer,我目前正在使用一个线程在控制台应用程序中每秒运行一个函数C#线程是最好的方法吗?我问过很多朋友,他们建议使用定时器而不是线程来每秒运行一些东西?如果使用计时器是一个更好的选择,我将如何使用计时器每秒运行一个函数?我环顾了四周,但我真的不确定这是否适用,也不确定这是否是以我自己的方式进行的正确方式。有人能告诉我答案吗?我该怎么做 那么,每秒运行它的最佳方式是什么?在你回答之前,让我告诉你,这是运行每一秒大约2天。。。 我当前的线程编码 namespace Reality.Game.Misc {

我目前正在使用一个线程在控制台应用程序中每秒运行一个函数C#线程是最好的方法吗?我问过很多朋友,他们建议使用定时器而不是线程来每秒运行一些东西?如果使用计时器是一个更好的选择,我将如何使用计时器每秒运行一个函数?我环顾了四周,但我真的不确定这是否适用,也不确定这是否是以我自己的方式进行的正确方式。有人能告诉我答案吗?我该怎么做

那么,每秒运行它的最佳方式是什么?在你回答之前,让我告诉你,这是运行每一秒大约2天。。。 我当前的线程编码

namespace Reality.Game.Misc
{
    using Reality;
    using Reality.Communication.Outgoing;
    using Reality.Game.Rooms;
    using Reality.Game.Sessions;
    using Reality.Storage;
    using System;
    using System.Data;
    using System.Threading;

    public static class JobCacheWorker
    {
        private static Thread jWorkerThread;

        public static void HandleExpiration(Session Session)
        {
             using (SqlDatabaseClient client = SqlDatabaseManager.GetClient())
            {
                Session.CharacterInfo.UpdateWorking(client, 0);
            }
        }

        public static void Initialize()
        {
            jWorkerThread = new Thread(new ThreadStart(JobCacheWorker.ProcessThread));
            jWorkerThread.Priority = ThreadPriority.Highest;
            jWorkerThread.Name = "JobCacheWorker";
            jWorkerThread.Start();
        }

        public static void CheckEffectExpiry(Session Session)
        {
            try
            {
                //RunMyCodeHere...
            }
            catch (Exception exception)
            {
                    Console.WriteLine("Exception - JobCacheWorker -> " + exception.Message);
            } 
        }

        private static void ProcessThread()
        {
            while (Program.Alive)
            {
                try
                {
                    foreach (Session Session in SessionManager.Sessions.Values)
                    {
                        if (Session != null && Session.Authenticated && !Session.Stopped)
                        {
                            CheckEffectExpiry(Session);
                            Thread.Sleep(1000);
                        }
                    }
                }
                catch (ThreadAbortException exception)
                {
                    Output.WriteLine("ThreadAbortException - JobCacheWorker -> " + exception.Message);
                }
                catch (ThreadInterruptedException exception2)
                {
                    Output.WriteLine("ThreadInterruptedException - JobCacheWorker -> " + exception2.Message);
                }
            }
         }
    }
}

如果希望任务与任何当前任务并行运行,那么使用线程不是一个坏选项。尽管如此,由于任务每秒钟都会发生,我认为这是一项非常小的任务。在这种情况下,最好使用定时器,因为它的代码更少,更容易理解。 为此,可以参考System类。它有一个例子和一切。
但总的来说,这些是你将要做的事情:

  • 创建计时器实例(最好全局声明并在initialize()中初始化)
  • 设置间隔(1秒=1000毫秒)
  • 启用计时器
  • 开始吧
  • 或者,如果需要,您甚至可以停止它
  • 我会使用一个线程,因为它通常比专用线程使用更少的资源。下面是一个例子:

    using System;
    using System.Threading;
    
    namespace Demo
    {
        public static class Program
        {
            public static void Main()
            {
                Console.WriteLine("Starting timer with callback every 1 second.");
    
                Timer timer = new Timer(callback, "Some state", TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
    
                Thread.Sleep(4500); // Wait a bit over 4 seconds.
    
                Console.WriteLine("Changing timer to callback every 2 seconds.");
    
                timer.Change(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));
    
                Thread.Sleep(9000);
    
                timer.Change(-1, -1); // Stop the timer from running.
    
                Console.WriteLine("Done. Press ENTER");
    
                Console.ReadLine();
            }
    
            private static void callback(object state)
            {
                Console.WriteLine("Called back with state = " + state);
            }
        }
    }
    
    对于控制台应用程序来说,这是一个不错的选择。但是,您必须记住,回调仍然是在主线程之外的单独线程上进行的,因此,在同步回调和主线程之间共享的资源和变量时必须小心。

    您可以查看哪个线程池定期执行单个回调,这比线程池更精确。 下面是您的代码的外观

    static void Main(string[] args)
    {
        TimerCallback tmCallback = CheckEffectExpiry; 
        Timer timer =  new Timer(tmCallback,"test",1000,1000);
        Console.WriteLine("Press any key to exit the sample");
        Console.ReadLine(); 
    }
    
    static  void CheckEffectExpiry(object objectInfo)
    {
        //TODO put your code
    }
    

    要考虑的主要问题是当前代码实际上不是每秒都运行。如果
    CheckEffectExpiry
    需要半秒,则每1.5秒运行一次(进程需要半秒,然后需要1秒睡眠,然后重复)。计时器可以让您每秒运行一个方法,但是您需要确保如果前一个方法仍在运行,那么您不会开始同时运行多个方法(假设这是您不希望的)。你可能想澄清精度在你的“每一秒”中有多重要。在这种情况下,睡眠比计时器更安全,因为1秒钟的小延迟。这取决于时间。如果您当前的方法是有效的,那么您忘了说出为什么它不够有效。还要注意:
    Thread.Sleep
    不包括函数本身执行所花费的时间,而
    Timer
    将为您提供连续准确的事件。准确性是有争议的,但是
    线程。1000次迭代后的睡眠
    会增加(累积)准确性,而
    计时器
    不会。几天后,我的线程崩溃并停止工作。这正常吗?是的,如果它崩溃了,那么它可能是由于代码中的某些错误造成的。崩溃的本质是什么?“如果您希望任务与任何当前任务并行运行,那么使用线程不是一个坏选项”您认为计时器在哪里执行代码?通常情况下,由于每件事情都是按顺序移动的,因此您的程序倾向于等待当前函数完成,然后才能继续执行,但使用线程,当线程完成其给定任务时,程序的其余部分可以继续工作。这就是为什么不允许也不建议在线程和主程序之间交换数据的原因之一。@Sanketh.K.Jain:Voo的观点是计时器也在一个单独的线程上运行,所以这不是两者之间的真正点。我如何每秒运行一次?我是C#@AshSimpson的新手,该行
    Timer Timer=new Timer(回调,“某些状态”,TimeSpan.FromSeconds(1),TimeSpan.FromSeconds(1))使其每秒运行一次。运行代码并检查输出。@MatthewWatson:我很感兴趣的是,你是否能够详细说明为什么Timer使用的资源比线程少,或者它是否很简单,因为它们都会使用一个额外的线程,但Timer只有在运行时才有它,而另一个线程会一直存在?@Chris Yes,您是正确的-计时器将只重用/创建线程池线程来发出回调,并且当计时器代码返回时,该线程将被释放。