web-dev-qa-db-ja.com

C#関数を毎秒実行する最良の方法、タイマーvsスレッド?

現在、コンソールアプリケーションで毎秒関数を実行するためにスレッドを使用しています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);
                }
            }
         }
    }
}
6
user4561879

System.Threading.Timer 専用のスレッドよりも一般的に使用するリソースが少ないため。次に例を示します。

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);
        }
    }
}

これは、コンソールアプリに適しています。ただし、もちろんコールバックはメインスレッドとは別のスレッドで実行されるため、コールバックとメインスレッド間で共有されるリソースと変数の同期には注意が必要です。

13
Matthew Watson

System.Threading.Timer を見てください。これは、一定の間隔でスレッドプールで単一のコールバックを実行するため、スレッドよりも正確になります。ここであなたのコードはどのように見えるか

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
}
5
BRAHIM Kamel

タスクを現在のタスクと並行して実行したい場合は、スレッドの使用は悪いオプションではありません。タスクは毎秒発生するため、非常に小さなタスクだと思います。その場合は、コードを減らして理解しやすくするために、タイマーを使用することをお勧めします。

そのためには、System Timer クラスを参照できます。それには例とすべてがあります。
しかし、一般的には、次のことを行います。

  1. タイマーのインスタンスを作成します(できれば、グローバルに宣言し、Initialize()で初期化します)
  2. 間隔を設定します(1秒= 1000ミリ秒)
  3. タイマーを有効にする
  4. 始めよう
  5. オプションで、必要に応じて停止することもできます
0