簡體   English   中英

如何在多線程應用程序中安全使用SmtpClient.SendAsync

[英]How to safely use SmtpClient.SendAsync in Multithreaded application

在我的應用程序中,我正在使用Dataflow庫中的ActionBlock通過SmtpClient.SendAsync()方法發送電子郵件警報,該方法不會阻止調用線程。( ActionBlockBufferBlock獲取數據,並且使用bufferBlock.LinkTo(actionBlock)塊綁定在一起bufferBlock.LinkTo(actionBlock) )。 但是,如果.SendAsync()另一個.SendAsync()調用,則此方法將引發InvalidOperationException

根據MSDN 文檔 ,發送操作完成時會引發public event SendCompletedEventHandler SendCompleted

如何確定由ActionBlock產生的線程(或Tasks )之間的爭用不會導致引發InvalidOperationException

到目前為止,我有一種想法是將圍繞SendAsync()調用的私有鎖和將分配給SendCompleted事件的私有函數添加到我的類(發送電子郵件)中。 當線程到達SendAsync()它獲取鎖,並在引發事件時,私有函數將鎖解鎖,從而允許其他線程獲取鎖並繼續前進。

為每個發送操作創建一個SmtpClient 這樣就無需同步任何內容。 只需將其封閉起來即可using

您應該只使用SendMailAsync 它將從調用SendAsync開始,並在引發SendCompleted時完成。

為了確保每次僅發送1條消息,您可以將SemaphoreSlim設置為1。它基本上是AsyncLock

但是,這將限制您的並行性,因為您一次只能執行一個操作。 您可以簡單地使用許多不同的客戶端。 如果每個調用都不是,則使用一些資源池,那么您可以具有並發性,但仍保持每個客戶端線程安全。

var client = _smtpClientPool.Get();
try
{
    await client.SendMailAsync(...)
}
finally
{
    _smtpClientPool.Put(client);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM