【问题标题】:Windows task scheduler terminate program doesn't work on forms applicationWindows 任务计划程序终止程序不适用于表单应用程序
【发布时间】:2016-01-08 14:50:55
【问题描述】:

我开发了一个 Windows 窗体程序,它也提供了批处理模式。它根据 SQL 表条目进行一些工作(每个条目一个操作)。

此程序已在任务调度程序中注册。

如果数据量很大,程序可能会运行好几个小时。

任务有如下配置:

  • 每 10 分钟运行一次
  • 仅当没有实例运行时
  • 如果当前实例运行时间超过 4 小时,则终止当前实例(以防永久挂起,这不应该发生,但我希望在安全站点上)

问题:kill 不起作用,但任务调度程序服务器认为它起作用了。所以它会在 0-10 分钟后开始下一个任务。导致多个任务运行。

幸运的是,重现类似问题很容易:

  • 刚开始任务
  • 然后点击“终止”(不确定这是否是正确的翻译,德语是“Beenden”)。

结果:任务调度程序显示没有运行 - 我可以再次启动任务。

这就是我的程序的构建方式(这是一个抽象但有效的复制示例):

程序.cs

static void Main()
{
    new frmTest().Auto(args);
}

frmTest.cs

public partial class frmTest : Form
{
    public frmTest()
    {
        InitializeComponent();
    }

    public void Auto(string[] args)
    {
        CancellationTokenSource tokenSource = new CancellationTokenSource();

        // Run a task which is cancellable every second.
        Task task = Task.Run(() =>
        {
            for (int i = 0; i < 60; i++)
            {
                Thread.Sleep(1000);
                tokenSource.Token.ThrowIfCancellationRequested();
            }

        }, tokenSource.Token);

        // Cancel the task when Application is trying to exit.
        Application.ApplicationExit += (o,e)=>
        {
            tokenSource.Cancel(); 
        };

        // We have to wait here. If we wouldn't, the main process would immedially including the current running task - for which we want to wait
        Task.WaitAll(task);
    }
}

注意:如果我不使用表单,则不会出现此问题(这是我第一次尝试抽象版本)。它一定与表格有关,但我不知道它可能是什么。

在调试模式下是否可以重现此问题?我的意思是发送一个信号或告诉应用程序退出(没有强制退出)的东西。

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    您应该使用Application.Run() 来启动应用程序运行。然后,您将不需要使用Task.WaitAll() 来“阻止”应用程序退出:

    static void Main()
    {
        var f = new frmTest().Auto(args);
        Application.Run(f);
    }
    

    但你可能想要,而不是,

        // Cancel the task when Application is trying to exit.
        Application.ApplicationExit += (o,e)=>
        {
            tokenSource.Cancel(); 
        };
    
        Task.WhenAll(task).ContinueWith(_=>{
          Application.Exit();
        });
    }
    

    【讨论】:

    • 谢谢!我会试一试并报告:)
    • 这行得通。非常感谢!我花了很多时间在这上面。 Application.Exit() 也是一个重要的提示。但还有一个问题:我注意到应用程序正在立即关闭 - 不是等待任务被取消。所以我添加了“Task.WaitAll(task);”在 ApplicationExit 事件中。这是合法的方式还是您会提出其他建议?
    猜你喜欢
    • 2018-08-25
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2017-03-24
    • 2023-04-03
    • 2014-02-03
    • 1970-01-01
    • 2012-03-26
    相关资源
    最近更新 更多