2012-01-19 115 views
-1

尋找如何解決這個問題的想法。這裏的交易:頭腦風暴解決方案---發送雙重電子郵件

我們有一個向我們發送公司零星這些坐在目錄中的文件。在我們這邊,我們有一個windows服務來監視那個目錄中的任何傳入文件。一旦服務運行並找到文件,它就會執行代碼來開始處理所述文件。該目錄一次可以有1到n個文件。因此,例如,我們可能有1000個文件出現在目錄中,並且Windows服務會查看這些文件,並啓動將數據存入數據庫併發送電子郵件的過程。

該進程運行多線程和異步。它抓取一個文件,將數據放入數據庫,然後發送電子郵件給某人。這裏的問題在於,當兩個進程正在運行並且它們都在打相同的代碼時,有時會爲同一個人生成2個電子郵件。方法如下:

  1. 轉到數據庫,看看我們有沒有聯繫。
  2. 是的,他在那裏,好吧,檢查'郵件標誌欄'...有郵件發送給他?
  3. 不,好吧,給他發一封電子郵件,並將'email flag column'標記爲YES(bool)。

發生了什麼事情是2線程在同一時間點擊此方法並同時讀取代碼。都查看數據庫並查看「電子郵件標誌列」是否。然後他們發送電子郵件並將列標記爲YES。但是,由於這種情況發生得太快,線程(A)在線程(B)讀取列之前沒有機會標記數據庫列。

我想過如果兩個線程在這個方法中背靠背,我們會放入一些代碼來'等待'。就像一個LOCK。但我們不能那樣做。我現在唯一的解決方案是不發送電子郵件。並有一個控制檯應用程序在一天的特定時間運行,併發送電子郵件給那些在該列中有0(否)的人。一旦電子郵件被髮送,然後我們將這些列標記爲1(是)。

它可能不是最好的解決辦法,這就是爲什麼我在這裏,讓你們中的一些怪異嚇人的聰明人來幫我想一些性感的解決方案。

+0

如果您正在閱讀和更新數據庫,則使用事務處理是針對類似於您的場景的常見和可證明的解決方案。 – Filburt

+1

順便說一句:SO不是論壇;它是一個問答網站。 –

回答

1

你需要一個鎖。

一種方法是有過程開始過程之前的電子郵件遷移到私有文件夾(這個過程)。只有一個進程可以移動文件。有你的鎖。

編輯

如果你決定使用一個數據庫來設置數據庫的鎖,要小心了。

除非你正在做一些特別的PInvokes獲得在Windows Vista,7事務文件系統或Windows Server 2008,你永遠在具有交易延伸到文件系統中的問題的危險。

0

如果您有多個進程和同步問題,則需要某種中央鎖,否則無法解決問題。不知何故,他們需要溝通。

如果你絕對不能像你所描述的過程,嘗試一箇中央「同步」服務器。 Redis會完成這項工作,它具有原子鍵操作。獲取文件時,設置一個密鑰的過程,一旦它打開並設置一個密鑰來說「我已經處理了這個文件,我是進程ID X」。如果其他人對該文件有鎖定,他們會取消該進程。在發送郵件之前再次檢查,以避免打開文件和設置鎖之間的進一步爭用問題

您可以將密鑰設置爲在一段時間後自動過期。

1

我會在閱讀時更新電子郵件標誌 - 通過使用SP或只是移動選擇並更新到相同的事務。例如,如果電子郵件發送失敗,則可以始終將其返回0.

+1

SELECT xxx FROM yyy ** FOR UPDATE **將在數據庫中設置一個鎖。 –

+0

hummmm,所以也許把SQL查詢放在一個USING(c#)或一個事務塊中可能會訣竅....? – user1158555

+0

C#'using'實際上與數據庫併發無關 - 數據庫事務是應該做的伎倆。 –

相關問題