2011-11-23 47 views
7

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

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

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

回答

7

作为一个情况下,你可以通过一个类封装了所有参数:

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

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

    // ... 
} 
+2

我打算把它给你,因为这可能是最“可读”的方法,并且我确信我的同事已经对我的大部分代码感到困惑。 –

+1

我没有看到任何好处。为什么在编译器可以为你做所有这些样板工作时自己创建一个类? –

+3

@Jon你有一点,我也是用编译器把踏板推向金属的粉丝。但是我也认为在某些情况下,为了让其他人能够毫无困难地理解代码,让代码变得更加冗长是很好的。相反,可以说我应该添加更多的内置评论。 –

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

非常令人印象深刻。我有点困惑,为什么在这个方法中间投下一个不好的东西?这是出于可读性还是会导致实际问题? –

+3

@RepoMan:为了可读性,这只是“正义” - 但从我的角度来看,这只是一个很大的“公正”:) –

1

它们是已知参数吗?然后用你需要的所有属性发送一个目标构建的对象。

1

这很好。您也可以构建自己的类型,并使用它来包含要传递给回调的参数。只需将“对象状态”参数转换为您已构建的类型并从类型中读取属性即可。

0

您可以创建一个封装所有需要传递的参数的类,或者可以使用lambda表达式。像这样的东西应该是非常接近的:

public void SendEmailsRepeatedly(IEnumerable<string> emails, int sendRepeatedlyDelayMS) 
{ 
    AutoResetEvent resetEvent = new AutoResetEvent(false);  
    Tokenizer tokenizer = new StandardTokenizer();   

    var timer = new Timer(x => SendRepeatedlyCallback(x, emails, tokenizer), resetEvent, 0, sendRepeatedlyDelayMS); 
} 

static void SendRepeatedlyCallback(object state, IEnumerable<string> emails, StandardTokenizer tokenizer) 
{ 
    ... 
} 
相关问题