0

C# を使用して .net 2.0 のマルチスレッド アプリケーションで System.Timers を使用しています。各スレッドは、タイマー経過イベントに異なる時間間隔を設定することになっています。

これが私のシナリオです:

D://ThreadingDemo/Clients というルート フォルダーがあります。これで、Clients フォルダーに n 個のフォルダーを含めることができます。1 と 2 としましょう (実際のシナリオでは、クライアントの数に等しい)。各フォルダーには、xml 構成ファイル (クライアント固有の詳細を含む) があります。

1 の設定:

ApplicationName: クライアント 1 のアプリケーション サポート

クライアントコード: A

時間間隔: 5000

2 の設定:

ApplicationName: クライアント 2 のアプリケーション サポート

クライアントコード: B

時間間隔: 2000

これで、私のアプリケーションはクライアントの数と同じ数のスレッドを作成します。この場合、2 つのスレッドとスレッド内の時間間隔を設定します。
5000 ミリ秒間隔のスレッド 1 と 2000 ミリ秒間隔のスレッド 2

以下は私が取り組んでいるコードです:

名前空間 ConsoleApplication3

{

class Program

{

    static string location = "D:\\ThreadingDemo\\Clients\\";
    public static System.Timers.Timer emailTriggerTimer = new System.Timers.Timer();
    static Double timeinterval;

    static void Main(string[] args)
    {

        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(location);
        Thread th;
        foreach (System.IO.DirectoryInfo g in dir.GetDirectories())
        {
            th = new Thread(() => DoWork(g.Name)); //** Passes CLIENT NAME to the method
            th.Name = g.Name;
            th.Start();
            Console.WriteLine(" ThreadStart - ClientName : " + g.Name + " " + DateTime.Now);
        }
        Console.ReadKey();
    }

    public static void DoWork(string fname)
    {

        emailTriggerTimer.Interval = GetsExecutionTimeFromConfigFile(); //** Gets Client specific FIRST EXECUTION TIME and converts to Time Interval
        emailTriggerTimer.Elapsed += new System.Timers.ElapsedEventHandler((sender, e) => emailTriggerTimer_Elapsed(sender, e, fname));
        emailTriggerTimer.Enabled = true;
        emailTriggerTimer.AutoReset = true;
        emailTriggerTimer.Start();

        Console.WriteLine(" DoWork - ClientName :" + fname + " " + DateTime.Now);
    }

    private static object emailTriggerTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e, string fname)
    {
        emailTriggerTimer.Stop();
        emailTriggerTimer.Enabled = false;

        Console.WriteLine(fname + " Elapsed "   + DateTime.Now);
        emailTriggerTimer.Interval = GetsTimeIntervalFromConfigFile(); //** Gets Client specific TIME INTERVAL

        emailTriggerTimer.Start();
        emailTriggerTimer.Enabled = true;
    }
}

}

私のコードは間違いなくタイマー間隔を台無しにし、両方のスレッドで最後のタイマー間隔、つまり2000ミリ秒を設定しています。以下の出力は次のとおりです。

ThreadStart - クライアント名:1 27/06/2013 12:13:12

ThreadStart - ClientName:2 2013/06/27 12:13:12

DoWork - ClientName:1 27/06/2013 12:13:12

DoWork - クライアント名:2 2013/06/27 12:13:12

ClientName : 1 経過 27/06/2013 12:13:13

クライアント名: 2 経過 27/06/2013 12:13:13

ClientName : 1 経過 27/06/2013 12:13:15

ClientName : 2 経過 2013/06/27 12:13:15

ClientName : 1 経過 27/06/2013 12:13:17

クライアント名: 2 経過 2013/06/27 12:13:17

ClientName : 1 経過 27/06/2013 12:13:19

ClientName : 2 経過 2013/06/27 12:13:19

ClientName : 1 経過 27/06/2013 12:13:21

ClientName : 2 経過 2013/06/27 12:13:21

ClientName : 1 経過 27/06/2013 12:13:23

ClientName : 2 経過 2013/06/27 12:13:23

私は、タイマーを使用したスレッドの概念にかなり慣れていません。各スレッドで経過するタイマー間隔を個別に設定する方法を誰かが提案していただければ幸いです。ありがとう!

4

2 に答える 2

1

すべてのスレッドに対して 1 つのタイマー オブジェクトを使用しているため、各スレッドのイベント ハンドラーがその 1 つのタイマーに追加されます。したがって、その 1 つのタイマー オブジェクトの間隔が満了すると、すべてのイベント ハンドラが実行されます。

解決策は、個々のスレッドごとにタイマー オブジェクトを作成することです。

このようなもの。

class Program {
    static string location = "D:\\ThreadingDemo\\Clients\\";
    static Double timeinterval;


    static void Main(string[] args) {
        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(location);
        foreach (System.IO.DirectoryInfo g in dir.GetDirectories()) {
            var th = new Thread(() => DoWork(g.Name)); //** Passes CLIENT NAME to the method
            th.Name = g.Name;
            th.Start();
            Console.WriteLine(" ThreadStart - ClientName : " + g.Name + " " + DateTime.Now);
        }
        Console.ReadKey();
    }

    public static void DoWork(string fname) {
        var emailTriggerTimer = new System.Timers.Timer();
        emailTriggerTimer.Interval = GetsExecutionTimeFromConfigFile(); //** Gets Client specific FIRST EXECUTION TIME and converts to Time Interval
        emailTriggerTimer.Elapsed += new System.Timers.ElapsedEventHandler((sender, e) => emailTriggerTimer_Elapsed(sender, e, fname, emailTriggerTimer));
        emailTriggerTimer.Enabled = true;
        emailTriggerTimer.AutoReset = true;
        emailTriggerTimer.Start();

        Console.WriteLine(" DoWork - ClientName :" + fname + " " + DateTime.Now);
    }

    private static void emailTriggerTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e, string fname, System.Timers.Timer emailTriggerTimer) {
        emailTriggerTimer.Stop();
        emailTriggerTimer.Enabled = false;

        Console.WriteLine(fname + " Elapsed "   + DateTime.Now);
        emailTriggerTimer.Interval = GetsTimeIntervalFromConfigFile(); //** Gets Client specific TIME INTERVAL

        emailTriggerTimer.Start();
        emailTriggerTimer.Enabled = true;
    }
}
于 2013-06-27T11:42:06.353 に答える
0

これは私にとってはうまくいくようでした。簡単な変更でこれを再訪しました。最初の実行はタイマーによって設定されたのではなく、スレッドをスリープ状態にすることによって行われました。タイマーに設定された間隔(最初の実行後)は完全に機能しました。コードは次のとおりです。

クラス プログラム

{

    static string location = "D:\\ThreadingDemo\\Clients\\";
    static Double timeinterval;
    public static System.Timers.Timer emailTriggerTimer;
    static void Main(string[] args)
    {

        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(location);
        Thread th;
        foreach (System.IO.DirectoryInfo g in dir.GetDirectories())
        {
            th = new Thread(() => DoWork(g.Name));
            th.Name = g.Name;
            th.Start();
            Console.WriteLine(" ThreadStart - ClientName :" + g.Name + " " + DateTime.Now);
        }
        Console.ReadKey();
    }

    public static void DoWork(string fname)
    {

        Thread.Sleep(Convert.ToInt32(GetsExecutionTimeFromConfigFile()));//** Gets Client specific FIRST EXECUTION TIME and converts to Time Interval           

        emailTriggerTimer  = new System.Timers.Timer();
        emailTriggerTimer.AutoReset = true;
        emailTriggerTimer.Elapsed += new System.Timers.ElapsedEventHandler((sender, e) => emailTriggerTimer_Elapsed(sender, e, fname));
        emailTriggerTimer.Interval =  GetsTimeIntervalFromConfigFile(); //** Gets Client specific TIME INTERVAL
        emailTriggerTimer.Enabled = true;

        emailTriggerTimer.Start();

        Console.WriteLine(" DoWork - ClientName :" + fname + " " + DateTime.Now);
    }

    private static void emailTriggerTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e, string fname)
    {

        Console.WriteLine("ClientName : " + fname + " Elapsed " + " " + DateTime.Now );
    }


}
于 2013-07-04T09:29:52.657 に答える