如果条件不适用于多线程

时间:2016-03-28 19:27:16

标签: c# multithreading

我写了这个管理器类,它保存了所有加载的位图。 我不想两次存储相同的位图,因此我会检查是否已有BitmapHolder具有相同的持久性名称(toString()对象方法。)

问题是,Add()中的签入将被忽略(或者看起来似乎),即使不应该。最后,这个类在列表中保存了几个相同的对象。

public class LazyStatic<T> where T : new()
{
    protected static T _static;
    public static T Static
    {
        get
        {
            if (_static == null) _static = new T();
            return _static;
        }
    }
}

public class BitmapManager : LazyStatic<BitmapManager>
{
   private List<BitmapHolder> _bitmaps;

   public BitmapManager()
   {
       _bitmaps = new List<BitmapHolder>();
   }

   /// <summary>
   /// Will add a loaded bitmap to the internal list.
   /// </summary>
   public void Add(Bitmap b, string persistenceName)
   {
       lock (_bitmaps)
       {
           if (GetBitmap(persistenceName) != null)
               return;
           BitmapHolder bh = new BitmapHolder
           {
               Bitmap = b,
               PersistenceName = persistenceName
           };
           _bitmaps.Add(bh);
       }
   }

   /// <summary>
   /// Will run through the internal list and look for a bitmap
   /// with the matching persistence name. Will return target if
   /// exists, otherwise null.
   /// </summary>
   public Bitmap GetBitmap(string persistenceName)
   {
       lock (_bitmaps)
       {
           foreach (BitmapHolder bhs in _bitmaps)
           {
               if (bhs.PersistenceName.Equals(persistenceName))
                   return bhs.Bitmap;
           }
           return null;
       }
   }

我的问题是。如何防止该方法忽略&#39; if条件。

2 个答案:

答案 0 :(得分:1)

Static的吸气器存在潜在的竞争条件,它不受锁定保护。竞争条件可能导致创建_static成员的重复实例,并且每个实例都将保存具有相同名称的位图。如果默认情况下实例化静态成员,则可以避免:

public static class LazyStatic<T> where T : new()
{
    private static T _static = new T();

    public static T Static
    {
       get
       {
          return _static;
       }
    }
}

如果您想进一步推迟实例化:

 public static class LazyStatic<T> where T : new()
{
    private static T _static = new Lazy<T>();

    public static T Static
    {
       get
       {
          return _static.Value;
       }
    }
}

答案 1 :(得分:-1)

编码异步时必须记住的一件事是全局对象可以由另一个线程更改MID-PROCESS。始终并始终在多线程操作期间实例化本地对象。传入全局使用的对象引用会产生不稳定的结果。