C#异步调用方法定时执行

9

应用程序的主线程正在做一些工作。

还有一个定时器,应该每隔10分钟调用某个方法,该方法应该以异步方式运行。

你能否给我一个好的例子来组织这个?


2
这是ASP.NET吗,还是表单,还是其他? - Justin Helgerson
这是一个Windows服务,实际上是一个服务器,始终在等待新的连接。因此没有GUI界面,但服务器工作不应该停止。 - Ksice
4个回答

14

我不建议使用带有循环和睡眠的显式线程,这是一种不好的做法并且很丑陋。因此,有定时器类可用:

如果这不是一个GUI应用程序,则可以使用System.Threading.Timer在不同的线程上周期性地执行代码。

如果这是一个WinForms/WPF应用程序,请查看System.Windows.Forms.TimerSystem.Windows.Threading.DispatcherTimer。它们非常方便,因为它们在GUI线程上执行其代码,因此无需显式调用Invoke

每个链接中也包含相应的示例。


只是出于好奇,如果这些计时器在GUI线程上执行,它们会阻塞主应用程序,因此单独的线程对于异步需求来说肯定更好吧?虽然我同意为每10分钟的执行保持一个完整的线程并不理想。 - Vok
@Vok:这取决于你需要做什么。这些计时器适用于快速定期更新GUI。如果代码运行时间更长,你应该使用System.Threading.Timer,并显式地使用Invoke来进行更新部分。无论如何,了解不同情况下可用的工具是很好的。 - Tudor
计时器的问题在于,无论上一个计时器事件是否完成,计时器都会触发。 - flotto

2

最简单的方法是调用一个大函数,在每个动作之间休眠10分钟。这不会阻塞任何东西,因为它在另一个线程中运行。

在.NET 4中,您可以使用Task类来实现:

Task t = Task.Factory.StartNew(() => { /* your code here */ });
// or
Task t = Task.Factory.StartNew(YourFunctionHere);

void YourFunction() {
    while (someCondition) {
        // do something
        Thread.Sleep(TimeSpan.FromMinutes(10));
    }
}

(此代码未经测试)

用 Task.Delay() 替换 Threas.Sleep 怎么样?除此之外,我能找到的最好的答案是:只使用任务并且非常简单。 - Martin Meeser
谢谢,但是当我写这个答案时,.NET 4.5 中的 Task.Delay(以及 asyncawait)还没有发布(只有 RC 版本)。最终版本是在两个月后发布的。 :-) - fero

0
使用BackgroundWorker线程。
void FireTask()
{
    BackgroundWorker bw = new BackgroundWorker();
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerAsync();
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    //Your job   
}

-3

启动另一个运行循环的线程

在循环内部;休眠10分钟,然后调用您的方法,重复执行


这种方法太昂贵了。 - Pritam Pawade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接