长时间运行的操作使用任务还是线程?

4

我有一个Windows服务,它运行两个方法;其中一个使用Ae.Net.Mail库每5分钟从三个电子邮件账户中读取未读邮件(我们称之为EmailParserWorker),另一个方法每30分钟执行另一个未指定的工作。因为这些方法必须每隔X段时间运行一次,所以我使用一个Timer来管理它们,并且它们工作得很好。

private Timer mailParserTimer;
private readonly TimeSpan SLEEP_TIME_MAIL_PARSER = TimeSpan.FromSeconds(300d);

/*...*/

public MyService()
{
    ServiceName = _serviceName;
    mailParserTimer = new Timer(new TimerCallback(EmailParserWorker), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
}
public void StartService()
{
    mailParserTimer.Change(SLEEP_TIME_MAIL_PARSER, Timeout.InfiniteTimeSpan);
    //EmailAnalyzer is a custom class I use to manage the accounts
    ea1 = new EmailAnalyzer(Config1); 
    ea2 = new EmailAnalyzer(Config2); 
    ea3 = new EmailAnalyzer(Config3); 
}

protected void EmailParserWorker(object state)
{
    try
    {
        // Pause timer during processing so it won't be run twice if the processing takes longer than the interval
        mailParserTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);

        // MANAGE THE THREE EMAIL ACCOUNTS
    }
    catch (Exception ex)
    {
        log.Error("[EmailParserWorker] Exception caught:" + ex.Message, ex.InnerException);
    }

    // Launch again in the specified time
    mailParserTimer.Change(SLEEP_TIME_MAIL_PARSER, Timeout.InfiniteTimeSpan);
}

我有一个问题,需要同时管理三个电子邮件帐户。我的经理要求我使用线程,以便它们可以同时运行。经过一番调查了解后,我对ThreadsTasks不确定哪个是最佳选择。我知道ThreadPooling不可行,因为我在某处看到如果操作持续时间超过几秒钟则不应使用它(我的肯定会持续更长的时间); 但Task是否使用此功能呢?我知道它有一个LongRunning选项,但我不知道我的进程是否符合要求。然后有Threads,它应该能够轻松处理这个问题,但我不知道它是否会在CPU使用方面效率极低。

基本上,我不知道应该使用其中的哪一个。现在我倾向于使用Tasks,但我不知道是否应指定LongRunning标记。而且,如果相关,则这些线程或任务将在使用计时器的方法内运行是否会影响任何内容?

1个回答

8
LongRunning 有效地意味着“立即始终启动新线程”。虽未记录,但出于兼容性原因,此行为永远不会更改。
应使用 TaskLongRunning。这严格优于 Thread。特别是错误处理和组合要好得多。
启动和销毁线程只需要几毫秒时间,大约1ms左右。不必担心启动3个线程。

这些线程或任务将在使用计时器的方法中运行是否会受到任何影响?

它们不会在计时器方法中运行。计时器方法将启动任务,这是一个快速操作。计时器 tick 回调在线程池上运行。这里没有什么问题,因为您正在将工作卸载到专用线程上。

谢谢您的回答!但是为了将来的实例,您说LongRunning表示“立即始终启动一个新线程”,那么对于不使用此标记的任务,这意味着什么?我仍然有点困惑它的含义。 - Ana Ameer
1
这些任务将被排队到线程池中。它的启发式并没有定义清楚或被理解。如果池中有很多工作排队,那么启动新项可能需要很长时间。如果池处于空闲状态,则新项会立即启动。这很复杂... - usr
2
LongRunning 表示仅为默认任务调度程序创建新线程。任何其他任务调度程序都可以忽略此选项,因为它不是必需的,只是一个提示。例如同步上下文任务调度程序 TaskScheduler.FromCurrentSynchronizationContext() 会忽略它并且只使用从捕获的同步上下文中的 Post 方法。 - user4003407
我想我将不得不继续独自调查;但就我的当前问题而言,这已经足够了,所以谢谢你。 - Ana Ameer

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