【问题标题】:How can I schedule tasks in a WinForms app?如何在 WinForms 应用程序中安排任务?
【发布时间】:2011-01-30 04:56:43
【问题描述】:

问题:如何在 WinForms 应用程序中安排任务?那是(a)最好的方法/.NET类/方法使用(b)如果有一个开源组件可以很好地做到这一点,那么会推荐一个。

背景:

  • Winforms 应用程序(.NET v3.5、C#、VS2008)
  • 我假设我将始终运行 winforms 应用程序,并在不使用时最小化到系统托盘
  • 想要一种简单的方法(不想进入运行 UI winform 应用程序与之对话的单独服务等)
  • 希望能够让用户选择计划同步的频率(例如,每小时、每天 - 选择时间等)
  • 能够在调度程序触发以运行一段代码时(例如,假设它可以被包装为后台工作任务)
  • 应用程序始终在运行并出现在系统托盘中

【问题讨论】:

    标签: .net winforms .net-3.5 scheduling


    【解决方案1】:

    实际上有Windows 中直接内置的东西 可以做到这一点。它被称为 Windows 任务计划程序!与其让 Windows 应用程序等待适当的时间运行一段代码,不如使用底层系统实用程序并将代码段存储在单独的可执行文件中运行:它是 更容易更高效

    我之前使用过任务计划程序将我的应用程序配置为按非常具体的计划启动。从 .NET 应用程序中执行此操作的最佳方法是使用this handy little library

    基本上,要完成您在问题中所述的内容,您需要制作一个提供 GUI 的 Windows 应用程序。此 GUI 应具有管理任务创建和更改的选项。任务应该启动你必须运行的代码(你应该将它存储在一个单独的可执行文件中,可能作为一个透明的 WinForms 应用程序,因此是隐藏的。)

    这里有一些代码from the CodeProject article of the library itself 说明了如何创建任务:

    //Get a ScheduledTasks object for the local computer.
    ScheduledTasks st = new ScheduledTasks();
    
    // Create a task
    Task t;
    try {
        t = st.CreateTask("D checker");
    } catch (ArgumentException) {
        Console.WriteLine("Task name already exists");
        return;
    }
    
    // Fill in the program info
    t.ApplicationName = "chkdsk.exe";
    t.Parameters = "d: /f";
    t.Comment = "Checks and fixes errors on D: drive";
    
    // Set the account under which the task should run.
    t.SetAccountInformation(@"THEDOMAIN\TheUser", "HisPasswd");
    
    // Declare that the system must have been idle for ten minutes before 
    // the task will start
    t.IdleWaitMinutes = 10;
    
    // Allow the task to run for no more than 2 hours, 30 minutes.
    t.MaxRunTime = new TimeSpan(2, 30, 0);
    
    // Set priority to only run when system is idle.
    t.Priority = System.Diagnostics.ProcessPriorityClass.Idle;
    
    // Create a trigger to start the task every Sunday at 6:30 AM.
    t.Triggers.Add(new WeeklyTrigger(6, 30, DaysOfTheWeek.Sunday));
    
    // Save the changes that have been made.
    t.Save();
    // Close the task to release its COM resources.
    t.Close();
    // Dispose the ScheduledTasks to release its COM resources.
    st.Dispose();
    

    注意:priority 选项对我没有用,总是让应用程序崩溃。我建议你把它排除在外;通常,它并没有那么大的区别。

    还有更多代码示例on the article page,其中一些展示了如何更改任务的设置、列出所有计划任务等。

    【讨论】:

    • thansk Maxim - 知道这与使用 Shoban 建议的任务计划程序托管包装器相比如何吗? taskscheduler.codeplex.com
    • 刚查了那个,好像比较新。另外,我不知道我建议的那个是否适用于 Task Scheduler 2.0(Vista 和 Win7),但我会尝试一下。
    【解决方案2】:

    如果您不想要 Windows 服务,则可以选择使用 Windows 启动应用程序。您可以使用以下代码来执行此操作。

    Dim regKey As RegistryKey
    regKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
    regKey.SetValue(Application.ProductName, Application.ExecutablePath)
    regKey.Close()
    

    您所说的安排同步是什么意思?是差异服务吗?然后您可以使用计时器,然后将用户设置存储在 xml 文件或数据库中。如果你想要一个简单的存储,那么你可以使用My.Settings

    编辑:我认为唯一的方法是检查应用程序启动的日期,然后定期检查日期。另一种选择是以编程方式使用任务调度程序。 Task Scheduler Managed Wrapper 是一个开源包装器,您可以试用。

    【讨论】:

    • 对不起,我使用“同步”只会让事情变得复杂。它只是一个 Windows 应用程序,用户可以安排一个“任务”定期运行。我有一个数据库,所以可以在那里存储数据。所以使用 Timer 类似乎是要走的路,但是你必须在你的代码中进行日期/时间检查吗? (因为计时器似乎并没有任何基于日历的日程安排)
    • 是的...这(即任务计划程序托管包装器)是我一直在寻找的那种东西...您认为这是一种可靠的方法吗?换句话说,仅使用计时器并在您的应用程序中编写日期/时间检查代码会更健壮/安全吗?强大我想我的意思是我可以假设它可以在没有任何问题的任何 PC 上运行(alberit XP、vista 或 Windows 7 等)
    • 附言。我不认为 Shoban 你知道一个开源控件,它使用任务计划程序托管包装器,它已经开发了一个简单的对话框/UI 来让用户选择他们想要的计划?
    • @Greg .. 不知道执行此操作的控件 ;-) 抱歉。如果我有任何会发布。是的,它可以在 win xp 上运行。
    • 哦...如果我使用任务计划程序托管包装器运行,但这意味着我必须将我的代码从一个 WinForms 应用程序中拆分出来,不是吗?基本上我的任务代码可以(a)由用户在winforms应用程序中手动启动,(b)由用户安排。处理这个问题的最佳方法是什么?即(a)winforms 应用程序如何为手动运行案例调用代码,以及(b)任务如何为计划案例调用它?任务是否可以调用正在运行的 WinForms 应用程序来触发它?
    【解决方案3】:

    所以您想在应用中运行预定义代码而不是外部 exe 的任务?

    • 制作一个带有系统托盘图标的 winforms 应用程序。如果您使用 click once 进行部署,请将发布者名称设为“Startup”,以便在 Startup 目录中安装快捷方式。

    • 使用计时器检查计划并在需要时启动线程。将您的本地计划存储在 XML 文件中,以便使用 LINQ 轻松查询。

    • 您正在使用后台工作线程运行任务,因此线程已在使用中。

    但是,如果您想使用 Windows 任务计划程序,可以使用 API。不是一个优雅的模块,但它工作得很好。

    【讨论】:

    • ok - 所以像让定时器设置为 5 分钟,所以每 5 分钟你自己检查一次(在你自己的应用程序代码中)看看你是否已经越过了下一个预定点? (也就是说,你不能说每天晚上 11 点直接提醒我的代码吗?)
    • 使用计时器并不是那么准确,因为您是以预定义的时间间隔进行检查。如果你想精确一点,请使用 Windows 任务计划程序:它有一个非常优雅的 API wrapper
    • 感谢 Maxim - 请注意我在另一个以“哦...如果我运行...”开头的答案中的问题 - 对此欢迎的任何反馈
    • 是的,他说的。如果您想将任务安排为精确的执行时间,那么计时器根本就不准确。但是任务计划程序不能使用您程序中的代码块,您必须将它们全部定义为自己的程序。下面也指出了这一点。
    猜你喜欢
    • 2015-07-27
    • 2012-01-23
    • 2020-03-02
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多