[英]Run a continuous task from static main method using tasks?
我正在尝试将async / await引入新的代码库,以使其每x秒执行一次后台任务。
我有以下内容,但它永远永久停止,而无需运行操作(printStuff)。
using System;
using System.Threading.Tasks;
namespace ASyncTaskDemo
{
class Program3
{
public static void Main(string[] args)
{
Action action = printStuff;
ExecuteEvery(new Task(action), 5000).Wait();
//simulate the rest of the application stalling until shutdown events.
Console.ReadLine();
}
private static int x = 0;
private static void printStuff()
{
Console.Error.Write(x++);
}
private static async Task ExecuteEvery(Task execute, int milliseconds)
{
while (true)
{
var delay = Task.Delay(milliseconds);
await Task.WhenAll(delay, execute);
}
}
}
}
如何确保任务在正确的线程上运行,甚至根本没有运行?
execute应该是运行时间较长的数据库摘要查询。 毫秒预计在几秒到几分钟的范围内,并希望计时的准确性。
“正确的线程”是指任务应在异步/网络环境中执行,而不是与主程序分发同步。
但是,如果可以重复使用此代码,有时可能需要在UI线程或服务器线程中运行任务,并且如果能解释该线程以及如何配置它,我将不胜感激。
您实际上从未启动过任务。 确实,恕我直言,将execute
表示为任务没有任何意义。 只需传递代表本身:
class Program3
{
public static void Main(string[] args)
{
Action action = printStuff;
ExecuteEvery(action, 5000); // ignore returned task
//simulate the rest of the application stalling until shutdown events.
Console.ReadLine();
}
private static int x = 0;
private static void printStuff()
{
Console.Error.Write(x++);
}
private static async Task ExecuteEvery(Action execute, int milliseconds)
{
while (true)
{
await Task.Delay(milliseconds);
execute();
}
}
}
还要注意,如果调用Wait()
,则永远不会读取ReadLine()
。 我已在上面的版本中将其删除。
我有以下内容,但它永远永久停止,而无需运行操作(printStuff)。
发生这种情况是因为您传递给executeEvety的Task
是使用'Task'构造函数创建的,因此,如果您未显式运行它,则不会安排它运行,因此等待您等待未启动的任务完成-这永远不会发生。
相反,您应该将Action
传递给executeEvery,并在每次循环迭代时都调用它,而无需异步调用:
ExecuteEvery(action, 5000).Wait();
private static async Task ExecuteEvery(Action action, int milliseconds)
{
while (true)
{
await Task.Delay(milliseconds);
action();
}
}
如果动作是长时间运行的。 如果您想在后台运行它,而不必等到下一次迭代(触发并忘记)之前完成, Task.Run
在调用它时添加Task.Run
:
private static async Task ExecuteEvery(Action action, int milliseconds)
{
while (true)
{
await Task.Delay(milliseconds);
Task.Run(() => action());
}
}
但是,忘了无休止的循环并使用Timer实现您想要的效果会更好吗?
创建Task
不会自动启动它。 您正在等待一个由于尚未启动而永远不会完成的Task
。 您应该使用Task.Run()
启动Task
我在下面修改了您的代码:
public static void Main(string[] args)
{
Action action = printStuff;
ExecuteEvery(action, 5000).Wait();
//simulate the rest of the application stalling until shutdown events.
Console.ReadLine();
}
private static int x = 0;
private static void printStuff()
{
Console.Error.Write(x++);
}
private static async Task ExecuteEvery(Action execute, int milliseconds)
{
while (true)
{
var delay = Task.Delay(milliseconds);
await Task.WhenAll(delay, Task.Run(execute));
}
}
我最终通过使用Func<Task>
而不是Action<Task>
这样就可以使用async方法而不是函数,并且可以使用async关键字适当地修饰其他方法。
/// <summary>
/// Executes a task every x milliseconds, but will wait for long running tasks to complete.
/// </summary>
/// <param name="execute">A Task Producer</param>
/// <param name="milliseconds">How often to run execute</param>
/// <param name="cancel">A cancellation token</param>
/// <returns></returns>
private async Task ExecuteEvery(Func<Task> execute, int milliseconds, CancellationToken cancel)
{
while (true)
{
var delay = Task.Delay(milliseconds, cancel);
await Task.WhenAll(delay, execute());
if(cancel.IsCancellationRequested) break;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.