循环运行任务
我有一个函数可能需要 5-60 秒才能运行,我需要每 10 秒运行一次,但它应该仅在先前启动的函数完成运行时才启动,我现在的代码是
Action myAction = new Action(() =>
{
Debug.WriteLine("just testing");
Thread.Sleep(15000);
});
Task myTask = Task.Factory.StartNew(myAction, _cts.Token);
Timer myTimer = new Timer(state =>
{
if (myTask.IsCompleted)
{
myTask = Task.Factory.StartNew(myAction, _cts.Token);
}
}, null, 10000, 10000);
一切正常,但我想知道如果我的问题有更好的解决方案吗?或者是否有可能不创建新任务(Task.Factory.StartNew)而仅使用 myTimer 使用的任务?
I have a function which can take 5-60 seconds to run, and I need to run it for every 10 seconds but it should be started only when the previously started function finished running, my code for now is
Action myAction = new Action(() =>
{
Debug.WriteLine("just testing");
Thread.Sleep(15000);
});
Task myTask = Task.Factory.StartNew(myAction, _cts.Token);
Timer myTimer = new Timer(state =>
{
if (myTask.IsCompleted)
{
myTask = Task.Factory.StartNew(myAction, _cts.Token);
}
}, null, 10000, 10000);
Everything is working fine but I wonder if there is a better solution for my problem? Or is there a possibility to not create a new task (Task.Factory.StartNew) but just using the one used by myTimer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用ContinueWith():
查找它的重载,它有很多选项来控制在哪些情况下运行延续。
You can use ContinueWith():
Look for it's overloads, it has many options to control on which cases to run the continuation.
有一个很棒的开源任务调度程序,称为 Quartz.net。您可以在 http://quartznet.sourceforge.net/ 找到它,
它支持您提到的特定场景。这是一个非常强大的解决方案,具有良好的可扩展性。
There is a great open source task scheduler called Quartz.net. You can find it at http://quartznet.sourceforge.net/
It supports the specific scenario you mentioned. It is a very robust solution with good extensibility.
如果您喜欢冒险,另一种可能性是使用 Rx:
使用 TakeUntilCanceled 扩展:
Another possibility, if you are adventurous, would be to use Rx:
Using the TakeUntilCanceled extension:
更好的想法是,不要尝试每 10 秒调用一次,而是依赖任务完成时的回调,如以下代码中的示例:
BackgroundWorker 类的功能使得事件处理程序
DoWork
在调用RunWorkerAsync()
时执行,在DoWork
完成时调用RunWorkerCompleted
。A much better idea would be to, instead of trying to call it every 10 seconds, rely on a callback on task completion, as an example in the following code:
The BackgroundWorker class functions such that the event handler
DoWork
is executed whenRunWorkerAsync()
is called andRunWorkerCompleted
is invoked whenDoWork
completes.您可以使用锁定语句。 lock 语句创建一个关键部分,对于给定对象一次只能运行其中一个。
使用主线程和任务线程都可以访问的对象作为互斥锁。围绕任务函数的代码和使用 lock 语句启动任务的行将实现您的目标。任务函数将获取锁,并且在完成之前不会释放它,而创建函数将等待获取锁,然后再创建另一个任务。
在启动操作的代码中,
You can use a lock statement. A lock statement creates a critical section, only one of which can be run at once for a given object.
Use an object both your main thread and your task thread can have access to as the mutex lock. Surrounding both the task function's code and the line that starts the task with the lock statement will accomplish your goal. The task function will acquire the lock and will not release it until it has finished, and the creation function will wait to acquire the lock before it creates another task.
And in your code that kicks off the action,