Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tasks or Threads for a long-running operation?

I have a windows service that runs two methods; one uses the Ae.Net.Mail library to read unread emails from three email accounts every 5 minutes (let's call it EmailParserWorker), and the other method makes another unspecified job every 30 minutes. Because these methods have to be run every X amount of time, I use a Timer to manage them, and they work fine.

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);
}

The question I have is when I have to manage the three email accounts. My manager asked me to use threads so that they can run at the same time, and after investigating a bit about Threads and Tasks, I'm confused as to which is my best option. I know ThreadPooling is out of the question, since I read somewhere that those shouldn't be used if the operation will last more than a couple seconds (which mine certainly will); but doesn't Task use this functionality? I know it has a LongRunning option, but I don't know if my process qualifies as one. And then there's Threads, which should be able to handle this without problem, but I don't know if it'll be incredibly inefficient in terms of CPU usage.

Basically, I don't know which one of these I should use. For now I'm leaning towards Tasks, but I don't know if I should specify the LongRunning token. And also, if relevant, does the fact that these threads or tasks will be running inside a method using timer affect anything at all?

like image 256
Ana Ameer Avatar asked Feb 11 '23 11:02

Ana Ameer


1 Answers

LongRunning effectively means "always start a new thread right now". This is not documented but for compatibility reasons this behavior can never change.

You should use Task and LongRunning. This is strictly superior to Thread. Especially error handling and composition are much better.

Starting and destroying a thread is a matter of milliseconds. Like 1ms or so. Don't worry about starting 3 threads.

does the fact that these threads or tasks will be running inside a method using timer affect anything at all?

They will not be running in the timer method. The timer method will start the task which is a quick operation. Timer tick callbacks run on the thread-pool. This is not a concern here because you are offloading the work to dedicated threads.

like image 165
usr Avatar answered Feb 13 '23 03:02

usr