在C#应用程序中保持线程活动

时间:2009-11-20 09:18:42

标签: c# multithreading

  

可能重复:
  Locking main() thread

下面你会找到我的代码,Main调用两个线程,一个启动一个事件处理程序,它在更改后返回注册表项的值。另一个设置一个计时器,每隔几分钟就将更改写入一个XML文件。基本上我希望反复运行写操作,而我希望事件处理程序的启动只运行一次,但保持打开以接受事件。有没有办法做到这一点?任何等待处理程序仍然允许代码运行等?请注意,这是一个后台应用程序,没有控制台,因为我不希望任何用户与系统交互(我知道通常一种服务是要走的路,但当我在运行服务时询问类似问题时,我被告知要制作应用程序和应用程序对我如何运行它/使用它更有意义。)

public class main
{
    static void Main(string[] args)
    {
        runner one = new runner();
        runner two = new runner();

        Thread thread1 = new Thread(new ThreadStart(one.TimerMeth));
        Thread thread2 = new Thread(new ThreadStart(two.start));

        thread1.Start();
        thread2.Start();
    }
}

public class runner
{
    RegistryValueChange valuechange;
    List<regkey> RegKeys = new List<regkey>();
    static object locker = new object();

    public void start()
    {
            if (File.Exists("C:\\test.xml"))
            {
                file load = new file();
                RegKeys = load.read(RegKeys);
            }

            string hiveid = "HKEY_USERS";
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            string id = identity.User.ToString();

            string key1 = id + "\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows Messaging Subsystem\\\\Profiles\\\\Outlook\\\\0a0d020000000000c000000000000046";
            List<string> value1 = new List<String> { "01020402", "test" };

            valuechange = new RegistryValueChange(hiveid, key1, value1);
            valuechange.RegistryValueChanged += new EventHandler<RegistryValueChangedEventArgs>(valuechange_RegistryValueChanged);

            file test = new file();
            test.checkfile("C:\\test.xml");
    }

    void valuechange_RegistryValueChanged(object sender, RegistryValueChangedEventArgs e)
    {
    }

    public void TimerMeth()
    {
            System.Timers.Timer timer = new System.Timers.Timer();

            timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);

            timer.Interval = 300000;

            timer.Enabled = true;
    }

    private void OnElapsedTime(object source, ElapsedEventArgs e)
    {
        lock (locker)
        {
            file write = new file();
            write.write(RegKeys);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

  • 您不需要创建一个线程来启动计时器。您可以在主线程中启动计时器。它的函数将在来自threadpool的线程上运行。

  • 我不明白为什么你需要为start()函数创建一个线程。它需要在计时器首次工作之前至少部分运行。因此,您可以在主线程中执行RegKeys = load.read(RegKeys);(以及可能来自start的其他代码)。如果您坚持在单独的线程中运行它,请确保初始化RegKeys。它可以通过例如在初始化ManualResetEvent并在计时器回调中等待此RegKeys后设置ManualResetEvent

  • 您应该在流程退出时停止计时器。

  • 您需要等待已启动的线程使用Thread.Join方法停止,或者等待在完成时在线程中设置的某些WaitHandleManualResetEvent例如)。

答案 1 :(得分:0)

您的代码有几个问题。首先你的Start()方法应该循环。如果不是,它将执行一次然后退出,从而完成线程。

您的主应用程序只是启动线程然后退出,因此当代码到达应用程序的结束括号时,它就会结束。在退出Main方法之前,必须等待线程结束。

此外,整个过程可能很棘手。首先,定时器通过中断和窗口消息循环的窗口消息在主线程中执行,因为这是一个控制台应用程序,在定时器事件引发应用程序时肯定会完成。 Here您可以看到如何在控制台应用程序中使用计时器(请注意,它不需要在单独的线程中创建)。请注意,从线程池线程调用委托,从而避免在运行器“two”中创建。

最后,考虑到您必须让主应用程序保持运行,直到某些事情发生,然后才能退出。也就是说,您必须在Main上设置一个循环,以允许您的应用程序等待某些事情发生,无论是用户输入,网络消息还是其他......基本上您将等待“退出”命令。