当前位置:  开发笔记 > 编程语言 > 正文

.NET中的声明性线程安全性

如何解决《.NET中的声明性线程安全性》经验,为你挑选了2个好方法。

我需要使现有的应用程序线程安全.在适当的情况下(见下文),我决定在整个业务对象图中使用一个ReaderWriterLock.所有方法/属性必须如下所示:

public int MyReadOperation(string inputParam)
{
   rwLock.AcquireReaderLock(10000);
   try
   {
      // do all read operations
      ...
   }
   finally
   {
      rwLock.ReleaseReaderLock();
   }
}

public void MyWriteOperation(string input)
{
   rwLock.AcquireWriterLock(10000);
   try
   {
      // do all write operations
      ...
   }
   finally
   {
      rwLock.ReleaseWriterLock();
   }

}

但是我有很多方法可以覆盖,我从复制/粘贴的想法中吓坏了.受MethodImplAttribute的启发,我希望有一个这样的代码,同时表现为上面的代码:

[ReadOperation]
public int MyReadOperation(string inputParam)
{
   // do all read operations
   ...
}

[WriteOperation]    
public void MyWriteOperation(string input)
{
   // do all write operations
   ...
}

有没有办法在进入属性或方法之前/之后中断线程执行并添加线程安全预防措施?或者以某种方式利用C#的函数式语言特性,将方法的生产体嵌入到通用的ReaderWriterLock中获取"框架"?

一点背景:

我正在开发一个项目,通过.NET Remoting公开数据载体业务对象.但是,这些数据类不是可序列化的,而是MarshalByRef-s.这意味着所有客户端实际上读/写相同的业务对象.这是不可改变的,它是刻在石头上的.线程安全的希望是这些远程业务对象在远程客户端的眼中是只读的(认为它们会循环许多列表)并且所有写入操作都很好地分成专用的外观.我希望罕见的写入和频繁的读取.业务对象高度连接,它们非常"图形化".



1> Andrew Rolli..:

我会使用PostSharp做类似的事情.

它作为一个额外的构建步骤运行并插入相应的MSIL,但它会做你想要的.PostSharp属性定义看起来像这样(取决于您的确切实现).然后可以如上所述使用它们.

public sealed class ReadOperationAttribute : OnMethodBoundaryAspect
{
  // not quite sure how you manage your lock, so put this dummy method in.
  ReaderWriterLock _rwLock = ReaderWriterLock.GetCorrectReaderWriterLock();

  [ThreadStatic]
  static bool _isLocked;

  public override void OnEntry( MethodExecutionEventArgs e )
  {
    try
    {
        _rwLock.AcquireReaderLock(10000);
        _isLocked = true;
    }
    catch
    {
        _isLocked = false;
        throw;
    }
  } 

  public override void OnExit( MethodExecutionEventArgs e )
  {    
      if (_isLocked) 
      {
          _rwLock.ReleaseReaderLock();
          _isLocked = false;
      }
  } 
}

public sealed class WriteOperationAttribute : OnMethodBoundaryAspect
{
  // not quite sure how you manage your lock, so put this dummy method in.
  ReaderWriterLock _rwLock = ReaderWriterLock.GetCorrectReaderWriterLock();

  [ThreadStatic]
  static bool _isLocked;

  public override void OnEntry( MethodExecutionEventArgs e )
  {
     try
    {
        _rwLock.AcquireWriterLock(10000);
        _isLocked = true;
    }
    catch
    {
        _isLocked = false;
        throw;
    }
  } 

  public override void OnExit( MethodExecutionEventArgs e )
  {
      if (_isLocked) 
      {
          _rwLock.ReleaseReaderLock();
          _isLocked = false;
      }
  } 
}

编辑:更新以解决问题.(未经测试;))另外,请注意我在这个问题的评论称,微软建议使用ReaderWriterLockSlim优先于ReaderWriterLock.



2> Mr. Lame..:

首先,谢谢安德鲁(Andrew),他把我指向了 PostSharp。根据他的回答,我得出了最后一个答案。

[Serializable]
public class ReadOperationAttribute : PostSharp.Laos.OnMethodInvocationAspect
{
    public override void  OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        ReaderWriterLock rwLock = GetLock();
        rwLock.AcquireReaderLock(10000);
        try { eventArgs.Proceed(); }
        finally { rwLock.ReleaseReaderLock();}
    }
}
public class Foo
{
    [ReadOperation]
    public string Bar
    {

        get { return "stuff"; }
        set { Console.WriteLine(value); }
    }

    [ReadOperation]
    public void Test(string input)
    {
        Console.WriteLine(input);
    }
}

它完全符合我在问题中表达的内容,并且完全可以调试。如果我们声明整个程序集的属性,我们可以使其更加有用:

[assembly: ReadOperation(AttributeTargetElements=MulticastTargets.Method,
AttributeTargetTypes="MyNamespace.*")]

这样,我们不必修饰每个方法/属性,但是将这个属性放置在程序集中一次后,便可以使用ReaderWriterLock制动所有方法/属性。

另外,正如Andrew所指出的那样,如果您使用.NET3.5或更高版本,Microsoft建议使用ReaderWriterLockSlim。

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有