tags:

views:

246

answers:

3

Alright so here is the deal. I am trying to make a application thats a GUI application yet has no GUI. So when the application starts, it has a small form with a login screen ( i am done this part).

This the code for the main() in which the form runs but as soon as it is closed, i dispose of it.

    static void Main() {

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);                        
        //Create an instance of form1
        Form1 form1 = new Form1();          
        Application.Run(form1);

        if(form1.isLoggedIn) {             
            filename = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username);
            Flow palm = new Flow(new FlowArguments(form1.username, filename));
            MessageBox.Show("Thankyou, exiting...");
            form1.Dispose();                
        } 
    }

So as you can see after the form is closed, the main continues on the condition if someone is logged in. If you look carefully, theres a instance to the "Flow" class thats created

This is a very short class and here we go:

   public class Flow {

        //global variables
        FlowArguments FlowArgs;
        System.Threading.Timer tm;

        //constructor
        public Flow(FlowArguments fmg) {
            FlowArgs = fmg;

            tm = new System.Threading.Timer(Tick, null, 
                                            System.Threading.Timeout.Infinite, 10000);


            using(StreamWriter sw = new StreamWriter(FlowArgs.Filename)) {            
               //sw.writelines that SO doesnt really care for.               
            }

            //enable the timer
            tm.Change(0, 100);
        }

        public void Tick(object State) {
            Console.WriteLine("Hello");
            //a bunch of SteamWriter writeline methods that SO doesnt care for.
        }

        public void WriteProcesses(StreamWriter sw, DateTime dw) {
            var localAll = Process.GetProcesses().Where(o => o.ProcessName.ToLower() != "svchost");
            foreach(Process p in localAll) {
                sw.WriteLine("@" + p.ProcessName +
                             "[" + dw.ToString("ddMMyyhhmm") + "]" +
                             "[" + FlowArgs.Username + "]");
            }              
        }


    }

As you can see I do start the timer.. but since this uses System.Threading.Timer (because I read somewhere that the Form.Timer really isnt appropriate) it runs on a threadpool (as per MSDN) but while this is happening the main form has now exited out of main() and hence the program is closed.

What are my possible solutions? This timer will run every 10 minutes (grabbing the processes). After the GUI is closed, I plan on making a system icon tray that the user can use to close the program..

A: 

If you want to make the foreground thread wait you can use a WaitHandle.

http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx

Otávio Décio
A: 

Thankyou, thats what I need so this is what I've implemented:

      if(form1.isLoggedIn) {             
            //Create a wait handle for the UI thread.
            AutoResetEvent hold = new AutoResetEvent(false);

            filename = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username);
            Flow palm = new Flow(new FlowArguments(form1.username, filename), hold);

            //wait for the background thread to finish.
            hold.WaitOne(Timeout.Infinite);

            MessageBox.Show("Thankyou, exiting...");
            form1.Dispose();                
        }

As you see it passes a reference of the AutoResetEvent (from MSDN Timer Class example) to the constructor of the Flow class. From there i can call the "set" method to release the waiting thread. I understand that now.

however

hold.WaitOne(Timeout.Infinite);

waits for indefinate time.. i'd like to send a "command" to the Flow class to stop the timer and call the "set" method on the waithandle so that the UI thread can exit..

how do I send a "signal"..

NOTE: I have NOT decided where I am gonna put the System Tray icon. So if its easier for me to put it in the Flow class I'd do it.

masfenix
+3  A: 

Drop all that thread stuff and do it all in a form that implements the system tray icon. Put your timer in that form and everything you want is done.

Something like

LoginForm login = new LoginForm();
if(login.ShowDialog()==DialogResult.OK)
{
    Application.Run(new SystemTrayForm());
}
Brody
I would but I am trying to dispose of memory fast. This is because this program is going to be running in the background while a full screen game is playing.
masfenix