0

好吧,这就是交易。我正在尝试制作一个 GUI 应用程序但没有 GUI 的应用程序。所以当应用程序启动时,它有一个带有登录屏幕的小表单(我已经完成了这部分)。

这是表单运行的代码,main()但一旦关闭,我就将其处理掉。

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

因此,正如您在表单关闭后所看到的那样,如果有人登录,则 main 会继续运行。如果您仔细观察,就会Flow发现创建的类有一个实例。

这是一个非常短的课程,我们开始:

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 + "]");
        }              
    }
}

如您所见,我确实启动了计时器。但是由于它使用System.Threading.Timer(因为我在某处读到它Form.Timer确实不合适)它在线程池上运行(根据 MSDN),但是当这种情况发生时,主窗体现在已经退出,Main()因此程序关闭。

我可能的解决方案是什么?该计时器将每 10 分钟运行一次(抓取进程)。关闭 GUI 后,我计划制作一个系统图标托盘,用户可以使用它来关闭程序。

4

3 回答 3

3

删除所有线程内容并以实现系统托盘图标的形式完成所有操作。把你的计时器放在那个表格里,你想要的一切都会完成。

就像是

LoginForm login = new LoginForm();
if(login.ShowDialog()==DialogResult.OK)
{
    Application.Run(new SystemTrayForm());
}
于 2009-01-12T03:15:08.133 回答
0

如果你想让前台线程等待你可以使用 WaitHandle。

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

于 2009-01-12T02:30:19.613 回答
0

谢谢,这就是我需要的,所以这就是我实现的:

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

如您所见,它将 AutoResetEvent(来自 MSDN 计时器类示例)的引用传递给 Flow 类的构造函数。从那里我可以调用“set”方法来释放等待线程。我现在明白了。

然而

hold.WaitOne(Timeout.Infinite);

等待不确定的时间..我想向 Flow 类发送一个“命令”以停止计时器并调用等待句柄上的“set”方法,以便 UI 线程可以退出..

我如何发送“信号”..

注意:我还没有决定将系统托盘图标放在哪里。因此,如果我更容易将它放在 Flow 类中,我会这样做。

于 2009-01-12T02:49:14.877 回答