On the past few projects of mine I've run into situations where I need to pass multiple parameters to a Threading.Timer
callback method. Unfortunately, the constructor only accepts a single object
parameter. Not wanting to use global variables, the pattern I've started using to overcome this problem is to pass in an anonymous method when the timer is created and use the compiler's ability to capture variables to my advantage, like so:
public void SendEmailsRepeatedly(IEnumerable<SimpleEmail> emails, int sendRepeatedlyDelayMS)
{
Tokenizer tokenizer = new StandardTokenizer();
sendRepeatedlyTimer = new Timer(
SendRepeatedlyCallback,
(Action)delegate()
{
TokenizeAndSendEmails(emails, tokenizer);
},
0,
sendRepeatedlyDelayMS);
}
private void SendRepeatedlyCallback(object state)
{
if (!abort)
{
Action sendEmails = (Action)state;
sendEmails();
}
}
So my question is, is this a flagrant hack? Is there a better or recommended way to do this?
As a case you can encapsulate all parameters by a class:
public sealed class SendEmailParameters
{
public int RepeatCount { get; private set; }
...
}
private void SendRepeatedlyCallback(object state)
{
var parameters = (SendEmailParameters)state;
// ...
}
That's absolutely fine. As of C# 3 I'd use a lambda expression instead, personally - and use a separate local variable to avoid the cast in the middle of a method:
public void SendEmailsRepeatedly(IEnumerable<SimpleEmail> emails,
int sendRepeatedlyDelayMS)
{
Tokenizer tokenizer = new StandardTokenizer();
Action action = () => TokenizeAndSendEmails(emails, tokenizer);
sendRepeatedlyTimer = new Timer(SendRepeatedlyCallback, action, 0,
sendRepeatedlyDelayMS);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With