QUESTION: How can I schedule tasks in a WinForms app? That is either (a) what is the best approach / .NET classes/methods to use of (b) if there is an open source component that does this well which one would be recommended.
BACKGROUND:
- Winforms app (.NET v3.5, C#, VS2008)
- I'm assuming I will run the winforms application always, and just minimise to the system tray when not in use 开发者_如何学C
- Want a simple approach (didn't want to get into separate service running that UI winforms app talks to etc)
- Want to be able to let the user select how often to schedule the sync (e.g. hourly, daily - pick time, etc)
- Ability to at the times when the scheduler fires to run a chunk of code (assume it could be wrapped as a backgroundworker task for example)
- The application is always running & appears in the system tray
There's actually something directly built into Windows that will do just that. It's called the Windows Task Scheduler! Rather than having a Windows application that sits and waits for the right time to run a piece of code, you'd be better off just using an underlying system utility and storing the piece of code to run in a separate executable: it's easier and more efficient.
I've used the Task Scheduler before to configure my applications to start on a pretty specific schedule. The best way to do it out of a .NET application is to use this handy little library.
Basically, to accomplish what you've stated in your question, you need to make a Windows application that provides a GUI. This GUI should have options that regulate the creation and alteration of a Task. The Task should launch the code you have to run (you should store it in a separate executable, probably as a WinForms app that's transparent and, thus, hidden.)
Here's some code from the CodeProject article of the library itself that illustrates how to create a task:
//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();
NOTE: The priority
option never worked for me, always crashing the app. I recommend you leave it out; usually, it doesn't make that big a difference.
There are more code samples on the article page, some of which show how to change the settings of a Task, list all Scheduled Tasks, etc.
If you don't want a Windows service then starting the application with windows is an option. You can use the following code to do that.
Dim regKey As RegistryKey
regKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
regKey.SetValue(Application.ProductName, Application.ExecutablePath)
regKey.Close()
What did you mean by schedule the sync? Is it a diff service? Then you can use the timer and then store the user settings in an xml file or a DB. If you want a simple storage then you can use My.Settings.
Edit: I think the only way is to check for the date when the app starts and then check the date periodically. Another option is to use the task scheduler programatically. Task Scheduler Managed Wrapper is an open source wrapper which you can try out.
So you want to run tasks that are predefined code in your app and not external exes?
Make a winforms app with a system tray icon. If you are deploying using click once, make the Publisher name "Startup" so a shortcut installs in the Startup directory.
Use a timer to check against the schedule and launch threads if needed. Store you local schedule in an XML file so it can be easily queried with LINQ.
You are running your tasks with Background worker so threading is already in use.
If you wanted to use the Windows Task Scheduler however, there is an API for it. Not a graceful module but it works well enough.
精彩评论