2016-12-05 104 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"); 
    } 
} 

嗯,你的生产代码,你会做这个有点不同,但基本的想法是有专用的线程将要做锁定和解锁,这样,从哪个线程调用到应该锁定和解锁代码/资源的方法将不重要。 ..

希望这可以帮助你。

相关问题