简体   繁体   中英

Locking main() thread

Not exactly sure on the terminology here but here I go basically I have the main() thread of my application that starts and calls two threads, one sets up an event handler to wait for specific registry keys to change, while the other starts a timer to write any changes made to an xml file every 5 mins or so and runs continuously. The issue I have is that once the two methods called are initialized it goes back to main and ends the program. My relevant code sections can be found below, so any help would be appreciated:

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

        thread1.Join();
        thread2.Join();
    }

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)
    {
        file write = new file();
        write.write(RegKeys);
    }

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

            try
            {
                valuechange.Start();

            }
            catch
            {
                StreamWriter ut;
                ut = File.AppendText("C:\\test.txt");
                ut.WriteLine("error occured in starting management");
                ut.Close();
            }

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

        }

void valuechange_RegistryValueChanged(object sender, RegistryValueChangedEventArgs e)
        {
// deals with the returned values
}

Basically all the code works fine I've been testing it in a windows form application but now I need to run it in a standalone app with no interface in the background and need it to keep writing to the xml file and the change event to stay alive.

Try building this into a windows service .

This thread contains two suggestions for finding the logged on user from a windows service, but I am not sure if they work.

As you can expect, the Main() method is terminating because execution flows out of the Join() methods back to the main thread, and then terminates.

Either place loops in the methods TimerMeth() and start() , or more appropriately redesign the application into a Windows Service (as zac says).

You have a couple of issues.

Your first thread is simply creating a timer (which launches another thread). This thread is terminating very quickly, making your call to Join rather meaningless. What this thread should be doing is actually doing the waiting and the checking. You can easily adapt your code like this:

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

    timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);

    timer.Interval = 300000;

    timer.Enabled = true;

    try
    {
        while(true)
        {
            OnElapsedTime(null, null); // you should change the signature

            Thread.Sleep(30000);
        }
    }
    catch(ThreadAbortException)
    {
        OnElapsedTime(null, null);

        throw;
    }
}

Obviously you should change the signature of OnElapsedTime to eliminate the parameters, since they aren't used here.

I have a feeling that something is amiss in the way that the file handling is being done, but given that I don't understand exactly what that code does , I'm going to refrain from commenting. What, exactly, is the purpose of the file? Where is RegKeys defined?

Your methods will run once, then the thread will exit. There is nothing to keep them running.

Try this:

thread1.IsBackground = true;
thread2.IsBackground = true;

public void start()
{
 while(true)
 {
    // ... do stuff
    Thread.Sleep(1000*60*5) // sleep for 5 minutes
 }
}

public void TimerMeth()
{
    while(true)
    {
        file write = new file();
        write.write(RegKeys);

        Thread.Sleep(30000);
    }
}

As other posters have noted, you will also then need to ensure your main method doesn't exit. Making the application a windows service seems like a good way to solve this in your case.

You might also want to handle ThreadInterruptedException and ThreadAbortException on your threads.

And if you really want to get into the nitty gritty of threading, check out this Free C# Threading E-Book by Joe Albahari.

为了使主线程保持活动状态,最简单的方法之一是在函数的末尾添加以下行:

Thread.Sleep(Timeout.Infinite);

The Thread will terminate when your ThreadStart function returns, which allows the main thread to continue after Join() . Since you are just setting up a timer to fire off, the method will return very quickly. You need to provide a lock of some sort to keep your application from exiting.

Also, it doesn't look like you need to use threads at all to do what you are trying. Instead, just use the Timer and provide the lock to keep your Main() from terminating.

It looks to me like all of your functions are completing? ie, they all "fall out the bottom". Once all the functions have run through there is nothing left to do and your app will close. You want to run a loop of some sort in main.

You will also need to take a look at your timer. I suspect it is currently being garbage collected. You create it in the scope of your function but that function is being left so there is no longer a reference to your timer and it will be collected. Your timer needs to be a root.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM