2011-01-07 45 views
1

我有一種方法可以向設備發送3個Web請求,這會使其發送一條短信。 2個第一個請求分別設置了短信收件人和郵件正文。第三次觸發派遣。同步的「呼叫定製感知」方法返回值

很明顯,這種方法必須同步,因爲競爭將徹底搞亂短信配置過程。

這當然是非常漂亮的解是這樣的:

private object _smsLock 
private bool SendSmsSync(string recipientNumber, string body) 
{ 
    lock(_smsLock) 
    { 
     // 3 web requests are sent here 
     // false is returned if something goes wrong 
     return true; 
    } 
} 

然而,這種解決方案的缺點是,我們必須在同時呼叫將進行的順序完全沒有控制。

包含Queue,ManualResetEvents和線程的大量代碼當然可以做到。但我仍然想知道是否有人知道更簡單的方法來做到這一點。

討論:)

回答

1

這似乎是一個合理的方法來保護消息的發送。它將防止消息本身發生故障。

如果您需要跨多個消息進行同步,則一種選擇是使用生產者/消費者方案。這將允許你有一個單獨的線程,只是將這些消息按順序排除。

public class Sms 
{ 
    public class SmsMessage 
    { 
     public int RecipientNumber { get; private set; } 
     public string Body { get; private set; } 
     public Sms(int recipient, string body) 
     { 
      this.RecipientNumber = recipient; 
      this.Body = body; 
     } 
    } 

    // Include your code above... 

    private BlockingCollection<SmsMessage> messageQueue = new BlockingCollection<SmsMessage>(); 

    public void Send(SmsMessage message) 
    { 
      messageQueue.Add(message); 
    } 

    // Permanently stop sending messages... 
    public void Stop() 
    { 
      messageQueue.CompleteAdding(); 
    } 

    public Sms() 
    { 
     // Spawn a thread to pump messages as they arrive 
     Task.Factory.StartNew(() => 
      { 
        foreach(var message in messageQueue.GetConsumingEnumerable()) 
         SendSmsSync(message.RecipientNumber, message.Body); 
      }, TaskCreationOptions.LongRunning); 
    } 
} 

有了這個,你可以只創建一個SMS實例,並調用發送給排隊的消息。郵件將始終按順序發送。

此外,這應消除上面的鎖定的需要,因爲消息始終在單個使用者線程中發送。

+0

謝謝你帶領我走向System.Threading.Tasks,這是我從來沒有聽說過(可恥的是我!) 。 – 2011-01-07 03:22:34

+0

@Remy:順便說一句,如果你想要的細節,我有一個關於TPL(和相關命名空間)的** long **系列:http://reedcopsey.com/series/parallelism-in-net4/ – 2011-01-07 22:21:13

0

最簡單也是最合乎邏輯的答案應該是「不要那麼做」。

即:如果您需要按順序進行三次調用*,請勿將它們放在單獨的線程上 - 只需按順序編寫代碼即可。

(*好了,第一和第二可以被並行化,但爲什麼?)