views:

650

answers:

2

Possible Duplicate:
Locking main() thread

Hello,

Below you'll find my code, Main calls two threads, one initiates an event handler that returns the values of registry keys after they have been changed. The other sets up a timer which writes the changes to an XML file every few minutes. Basically I'm looking to run the write over and over while I wish the the initiation of the event handler to run only once, but remain open to accept events. Is there any way to do this? Any wait handlers which will still allow code to run etc? Please note that this is a background application, with no console as I don't want any user interaction with the system (I know typically a service is the way to go but when I asked similar questions when running a service I was told to make an application and an application makes more sense for how I want to run it/use it.)

Thanks for any help thats given beforehand.

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

You have several problems with your code. First your Start() method should do an loop. If it doesn't it will execute once and then exit, hence finishing the thread.

You main application just starts the threads and then exits, hence when the code reaches the closing bracket in your application it simply ends. You have to wait for the threads to end before exiting your Main method.

In addition, the whole process can be tricky. First, Timers execute in the main thread by means of an interruption and a window message to the window message loop, that you don't have since this is a console application, by the time the timer event raises your application will surely be finished. Here you can see how to use a timer in a console application (note that it doesn't need to be created in a separate thread). Note that the delegate is called from a thread pool thread, thus avoiding your creation in runner "two".

Finally, take into account that you'll have to keep your main application running until something happens to make it quit. That is, you'll have to setup a loop on your Main to allow your application to wait for something to happen, be it user input, network messages or whatever... basically you'll be waiting for the "quit" command.

Jorge Córdoba
+1  A: 
  • you don't need to create a thread just to start timer in it. You can just start timer in your main thread. Its function will run on a thread from threadpool.

  • I don't see why you need to create a thread for start() function. It needs to be run at least partially before your timer first work. So, you may execute RegKeys = load.read(RegKeys); (and probably other code from start) in main thread. if you insist on running it in separate thread, ensure that RegKeys is initialized. It can be done by, e.g. setting ManualResetEvent after initializing RegKeys and waiting for this ManualResetEvent in timer callback.

  • You should stop timer on process exit.

  • you need to wait for started thread's stopping using Thread.Join method or by waiting on some WaitHandle (ManualResetEvent e.g.) being set in thread on finish.

elder_george