C# Application.Run()、Application.Exit()和计时器

C# Application.Run()、Application.Exit()和计时器,c#,timer,scheduled-tasks,message-loop,C#,Timer,Scheduled Tasks,Message Loop,我有一个winforms应用程序,我将通过任务调度器调用它来下载文件并将其插入数据库。但是,当文件可用时,它是不可预测的,所以我使用了timer(System.Windws.Forms.timer)来轮询文件 static class Program { /// <summary> /// The main entry point for the application. /// </summary>

我有一个winforms应用程序,我将通过任务调度器调用它来下载文件并将其插入数据库。但是,当文件可用时,它是不可预测的,所以我使用了timer(
System.Windws.Forms.timer
)来轮询文件

 static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            if (args != null && args.Length > 0)
            {

                Form1 f1 = new Form1();
                if (f1.IsLive)
                {
                    f1.OnLaunch(); // tests DB connection and reads and updates the expiry date list.

                    if (args[0] == "FullStats")
                        f1.FullStatsDataPump();
                    else if (args[0] == "OptionsStats")
                    {
                        f1.OptionsStatsTimer_Tick(null, null);
                        f1.OptionsStatsTimer.Start();
                    }
                    else if (args[0] == "OptionsTraded")
                    {
                        f1._optionsTradedTimer_Tick(null, null);
                        f1.OptionsTradedTimer.Start();
                    }
                    else
                    {
                        EmailManager.InvalidInputArgument(args[0]);
                        Application.Exit();
                    }

                    Application.Run();
                }

            }
静态类程序
{
/// 
///应用程序的主要入口点。
/// 
[状态线程]
静态void Main(字符串[]参数)
{
如果(args!=null&&args.Length>0)
{
Form1 f1=新Form1();
如果(f1.IsLive)
{
f1.OnLaunch();//测试数据库连接,读取并更新到期日期列表。
如果(args[0]=“FullStats”)
f1.FULLSTATSDATAPPUMP();
else if(参数[0]=“optionStats”)
{
f1.选项StatsTimer_勾选(空,空);
f1.选项StatsTimer.Start();
}
else if(参数[0]=“期权交易”)
{
f1._optionsTradedTimer_勾选(null,null);
f1.OptionsTradedTimer.Start();
}
其他的
{
EmailManager.InvalidInputArgument(参数[0]);
Application.Exit();
}
Application.Run();
}
}
在上面的代码片段中,
OptionsTradedTimer
/
OptionsStatsTimer
都轮询文件,然后开始以
Application.Exit()
结束的进程。这运行得很好,但之后它会陷入无限的消息循环中。我认为
Application.Run()
将在第一个计时器计时后立即调用,因此当
Application.Exit()
最终被调用时,它将结束消息循环。但如果我单步执行代码,则在该
Application.Exit()之后,程序将返回计时器。tick()它从哪里开始,然后继续到底部的
应用程序.Run()
。底部的
应用程序.Run()
是必需的,因为没有它计时器只会滴答一次,然后应用程序就会退出


那么,我如何正确地告诉应用程序退出?或者我应该在哪里调用
application.Run()

听起来有点奇怪-也许您应该简单地将Application.exit移动到一个单独的过程,如果需要退出程序,只需更改一些布尔变量。在主程序中,您可以等待布尔值更改,然后退出程序一次。此外,您还可以同时将布尔变量设置为false开始,这样您就不需要运行了。

我认为您不需要使用Application.Exit()。您的Main()方法是应用程序的入口点;当它返回时,应用程序将退出。一般来说,Application.run()用于启动一直运行到关闭的windows窗体。请尝试一下此代码-我还没有测试过它,但它应该可以满足您的需要

using System.Linq;
using System.Threading;

class MyApplication
{
    [STAThread]
    static void Main(string[] args)
    {
        const string ARG_SHOWFORM = "ShowForm";
        const string ARG_STATS = "OptionsStats";
        const string ARG_TRADED = "OptionsTraded";

        if (args.Contains(ARG_SHOWFORM) || args.Length == 0) {
            Application.Run(new Form1());  //This will block until the form is closed.

            //Make sure all your supporting logic is placed into the Form.Loaded event on the form (i.e.
            //get it out of the Main() method).

            return;
        }

        if (args.Contains(ARG_STATS))
            OptionsStatsMethod();

        else if (args.Contains(ARG_TRADED))
            OptionsTradedMethod();

        else
            EmailManager.InvalidInputArgument(args[0]);

    }

    private void OptionsTradedMethod()
    {
        while (true) {
            if (downloadSuccessful) //Use a method here that returns a boolean if the download succeeded.
                break;
            else
                Thread.Sleep(DEFAULT_WAIT_TIME_MS);
        }
    }

    private void OptionsStatsMethod()
    {
        while (true) {
            if (downloadSuccessful)  //Use a method here that returns a boolean if the download succeeded.
                break;
            else
                Thread.Sleep(DEFAULT_WAIT_TIME_MS);
        }
    }
}

要使主方法保持运行(使其线程处于活动状态),可以使用thread.Sleep而不是Application.Run()。请尝试以下操作:

Thread.Sleep(System.Threading.Timeout.Infinite);
使用以下命令代替Application.Exit():


这种方式是有效的,但是考虑使用Windows Services来解决这个问题。

不能删除这个问题,所以不妨回答它。< /P> 只有当计时器第一次运行时到达

Application.Exit()
行时才会出现问题。(即,如果程序运行时文件已经可用)。在这种情况下,在
Application.run()之前调用
Application.Exit()
,其中就好像计时器没有到达
Application.Exit())
在第一次运行时(即文件尚不可用),然后调用
Application.run()
,然后调用
Application.Exit()

为了解决这个问题,我在计时器的tick方法中添加了一个条件,以确保它们在第一次运行时不会出现任何问题


我不同意按目前的方式重新构造程序。我可以通过任务调度器运行程序,每天下载文件,而无需使用表单和轮询功能。我还可以通过VS运行程序,作为一个普通的winforms应用程序,带有测试、调试和在出现问题时下载文件的按钮。

退出,因为在使用任务调度器时表单不会显示。表单只是提供了一个很好的测试和调试界面。向程序中添加一个选项以通过命令行显示表单如何?正如我所说,我认为这需要重新设计,以使它能够执行您希望它执行的操作。我不希望表单显示,我也不认为不管怎样,当通过调度程序运行时,它都会运行。表单是用于我通过VS运行它的,但我也需要每天通过任务调度程序运行它。我不知道如何摆脱计时器?对我来说,最明智的重新设计是使它成为windows服务,但我真的不想这样做,我非常确定这可以很容易地修复。它是j我们需要了解计时器和应用程序之间的时间。run()我将为您编写一组伪代码,这样您就可以看到我在说什么。谢谢。那么这是否意味着计时器将继续触发?以及如何告诉程序在需要时结束?如果您使用Thread.Sleep on the Main()的话线程,则会导致程序挂起。当有其他线程运行时(此处为计时器),程序不会挂起。请重试。Application.Exit()不会导致程序结束。程序在Main()返回时结束。Application.Run()创建一个消息循环(无限循环),该循环在Application.Exit()时终止调用。它不起作用的原因是代码没有逻辑意义。因此,您需要重新设计应用程序。
Process.GetCurrentProcess().Kill();