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个线程并在线程内设置一个时间间隔。
线程 1 的间隔为 5000 毫秒,线程 2 的间隔为 2000 毫秒

下面是我工作的代码:

命名空间 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 - 客户端名称:2 27/06/2013 12:13:12

DoWork - 客户名称:1 27/06/2013 12:13:12

DoWork - 客户名称:2 27/06/2013 12:13:12

ClientName : 1 经过 27/06/2013 12:13:13

ClientName : 2 经过 27/06/2013 12:13:13

ClientName : 1 经过 27/06/2013 12:13:15

ClientName : 2 已过 27/06/2013 12:13:15

ClientName : 1 经过 27/06/2013 12:13:17

ClientName : 2 经过 27/06/2013 12:13:17

ClientName : 1 经过 27/06/2013 12:13:19

ClientName : 2 经过 27/06/2013 12:13:19

ClientName : 1 经过 27/06/2013 12:13:21

ClientName : 2 经过 27/06/2013 12:13:21

ClientName : 1 经过 27/06/2013 12:13:23

ClientName : 2 经过 27/06/2013 12:13:23

我对使用计时器的线程概念很陌生。如果有人建议如何分别设置每个线程中经过的计时器间隔,我将不胜感激。谢谢!

4

2 回答 2

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 回答