将多个参数传递给Threading.Timer回调方法的最佳方法是什么?

Rep*_*Man 7 .net c# timer callback

在我过去的几个项目中,我遇到了需要将多个参数传递给Threading.Timer回调方法的情况.不幸的是,构造函数只接受一个object参数.不想使用全局变量,我开始用来克服这个问题的模式是在创建计时器时传入一个匿名方法,并使用编译器捕获变量的能力,如下所示:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,这是一个公然的黑客攻击吗?是否有更好或推荐的方法来做到这一点?

sll*_*sll 7

作为一种情况,您可以通过类封装所有参数:

public sealed class SendEmailParameters
{
    public int RepeatCount { get; private set; }
    ...
}

private void SendRepeatedlyCallback(object state)
{
    var parameters = (SendEmailParameters)state;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • @Jon你有一个观点,我也是用编译器将踏板推到金属上的粉丝.但是我也认为在某些情况下,让代码更加冗长,以便其他人可以毫不费力地理解它.相反,可以说我应该添加更多的内联评论. (3认同)
  • 我打算把它给你,因为这可能是最"可读"的方法,而且我确信我的同事已经对我的大部分代码感到困惑了. (2认同)

Jon*_*eet 6

那绝对没问题.从C#3开始,我个人使用lambda表达式 - 并使用单独的局部变量来避免方法中间的强制转换:

public void SendEmailsRepeatedly(IEnumerable<SimpleEmail> emails,
                                 int sendRepeatedlyDelayMS)
{
    Tokenizer tokenizer = new StandardTokenizer();
    Action action = () => TokenizeAndSendEmails(emails, tokenizer);    
    sendRepeatedlyTimer = new Timer(SendRepeatedlyCallback, action, 0,
                                    sendRepeatedlyDelayMS);
}
Run Code Online (Sandbox Code Playgroud)

  • @RepoMan:为了便于阅读,它"只是" - 但从我的观点来看这是一个很大的"公正":) (3认同)