2016-12-05 60 views
3

我有一些使用ReaderWriterLockSlim的代碼。當構造某個對象時,我會獲得一個寫入鎖定,並在某個對象稍後處理時釋放它。但是,由於這些調用來自哪裏,因此我不能保證它們將在同一個線程上,這是ReaderWriterLockSlim的要求。TaskScheduler始終運行在同一線程上

我相信一個合理的解決方案是在專用線程上運行對象的構建和處置,並讓調用代碼等待該任務完成(但保持線程活着)。這看起來很混亂,但我不能想到沒有大規模重組我們的代碼的另一種方法。

是否有一個現有的TaskScheduler子類允許我在同一個線程上運行兩個任務?

我當然可以打開另一個這樣做的範例。

+2

你使用的是WPF還是Windows.Forms?還是ASP.Net?這將大大影響答案:) – gnud

+0

有趣的是,包含ReaderWriterLockSlim的底層庫從多個應用程序中使用;一些在Windows窗體中,一些在WPF中;雖然有問題的情況是在我們的WPF應用程序中使用它。 – Smashery

+0

在WPF中創建的普通任務應全部在同一個線程(分派器線程)上運行。但是,對於「長期運行」的任務以及在線程池中顯式創建的任務,情況並非如此。 https://msdn.microsoft.com/magazine/gg598924.aspx – gnud

回答

0

我有類似的問題,所以我希望我的解決方案也能幫助你。

基本上,問題是ReaderWriterLockSlim具有線程關聯性,這意味着獲得鎖的線程是唯一可以釋放它的線程。

解決方法是創建一個專用線程,但與您的建議相反,此線程將專門用於獲取和釋放鎖定。

我猜你的代碼看起來是這樣的:

public class ClassUsingReaderWriterLockSlim 
{ 
    private ReaderWriterLockSlim rwsLock; 

    public void MethodThatAcquiresLock() 
    { 
     rwsLock.EnterWriteLock(); 
    } 

    public void MethodThatReleasesLock() 
    { 
     rwsLock.ExitWriteLock(); 
    } 
} 

和代碼能夠解決您的問題,看起來就像這樣:

public class ClassUsingReaderWriterLockSlim 
{ 
    private ReaderWriterLockSlim rwsLock; 
    Thread dedicatedThreadForReaderWriterLockSlim; 
    Queue<string> commandsForDedicatedThread; 

    public ClassUsingReaderWriterLockSlim() 
    { 
     commandsForDedicatedThread = new Queue<string>(); 
     dedicatedThreadForReaderWriterLockSlim = new Thread(ThreadFunction); 
     dedicatedThreadForReaderWriterLockSlim.Start(); 
    } 

    private void ThreadFunction(object obj) 
    { 
     while (!terminatingCondition) 
     { 
      // Wait until something is in queue... 

      if (commandsForDedicatedThread.Count > 0) 
      { 
       switch (commandsForDedicatedThread.Dequeue()) 
       { 
        case "ENTER LOCK": 
         rwsLock.EnterWriteLock(); 
        case "EXIT LOCK": 
         rwsLock.EnterWriteLock(); 
        default: 
        // Do nothing... 
       } 
      } 
     } 
    } 

    public void MethodThatAcquiresLock() 
    { 
     commandsForDedicatedThread.Enqueue("ENTER LOCK"); 
    } 

    public void MethodThatReleasesLock() 
    { 
     commandsForDedicatedThread.Enqueue("EXIT LOCK"); 
    } 
} 

嗯,你的生產代碼,你會做這個有點不同,但基本的想法是有專用的線程將要做鎖定和解鎖,這樣,從哪個線程調用到應該鎖定和解鎖代碼/資源的方法將不重要。 ..

希望這可以幫助你。

相關問題