2011-11-23 64 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) 
{ 
    ... 
} 
相關問題