【问题标题】:Tasks or Threads for a long-running operation?用于长时间运行的操作的任务或线程?
【发布时间】:2015-04-14 01:18:19
【问题描述】:

我有一个运行两种方法的 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 令牌。而且,如果相关的话,这些线程或任务将在使用计时器的方法内运行这一事实是否会影响任何事情?

【问题讨论】:

    标签: c# multithreading task-parallel-library


    【解决方案1】:

    LongRunning 实际上意味着“总是立即开始一个新线程”。这没有记录,但出于兼容性原因,此行为永远不会改变。

    您应该使用TaskLongRunning。这绝对优于Thread。尤其是错误处理和组合要好得多。

    启动和销毁线程只需几毫秒。像1ms左右。不用担心启动 3 个线程。

    这些线程或任务将在使用计时器的方法内运行这一事实是否会影响任何事情?

    它们将在计时器方法中运行。 timer 方法将启动一个快速操作的任务。计时器滴答回调在线程池上运行。这不是一个问题,因为您将工作卸载到专用线程。

    【讨论】:

    • 感谢您的回答!但是为了将来的实例,您说LongRunning 的意思是“总是立即开始一个新线程”;这对于不使用此令牌的任务意味着什么?我还是有点搞不懂它的意思。
    • 这些任务将排队到线程池中。它的启发式方法没有得到很好的定义或理解。如果池中有很多工作在排队,那么启动新项目可能需要很长时间。如果池处于空闲状态,则立即启动新项目。很复杂……
    • LongRunning 表示仅用于默认任务调度程序的新线程。任何其他任务调度程序都可以忽略此选项,因为它不是必需的,只是一个提示。例如同步上下文任务调度程序TaskScheduler.FromCurrentSynchronizationContext() 忽略它,只使用捕获的同步上下文中的Post 方法。
    • 我想我得自己继续调查;但对于我目前的问题,这会解决,所以谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-07-06
    • 2020-05-13
    • 1970-01-01
    • 2013-07-27
    • 2023-03-31
    • 2017-10-22
    • 2018-09-24
    • 1970-01-01
    相关资源
    最近更新 更多