Question

Can anyone tell me why this code is wrong and how I have to modify it in order to create a simple Bitmap of which is guranteed thread-safe access?

public static class ThreadSafe
{
    public static readonly object _locker = new object();
    public static Bitmap _snapshot;

    public static Bitmap Snapshot
    {
        get
        {
            lock (_locker)
            {
                return _snapshot;
            }
        }
        set
        {
            lock (_locker)
            {
                _snapshot = value;
            }
        }
    }

}

EDIT How I want use that Bitmap:

  • Thread A use the Bitmap in this way:

new Bitmap(ThreadSafe.Snapshot, new System.Drawing.Size(320, 240));

  • Thread B uses the Bitmap in this way:

ThreadSafe.Snapshot = new Bitmap(target, new System.Drawing.Size(320, 240));

Était-ce utile?

La solution

Following the thread safety guidelines from the Bitmap documentation;

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

...this should be close to the minimum locking implementation;

public static class ThreadSafe
{
    private static readonly object BitmapLock = new object();
    private static Bitmap _snapshot;

    public static Bitmap Snapshot
    {
        get
        {
            lock (BitmapLock)
                return new Bitmap(_snapshot);
        }
        set
        {
            Bitmap oldSnapshot;
            Bitmap newSnapshot = new Bitmap(value, new Size(320, 240));
            lock (BitmapLock) 
            {
                oldSnapshot = _snapshot;
                _snapshot = newSnapshot;
            }
            if (oldSnapshot != null)
                oldSnapshot.Dispose();
        }
    }

}

Autres conseils

If these are the only 2 things that you do with the bitmap:

new Bitmap(ThreadSafe.Snapshot, new System.Drawing.Size(320, 240));
ThreadSafe.Snapshot = new Bitmap(target, new System.Drawing.Size(320, 240));

Then congratulations, you are threadsafe already without any need for extra work at all (just add volatile):

public static class ThreadSafe
{
    public static volatile Bitmap Snapshot;
}

My solution, with a dispose implementation for the snapshot copy:

public static class ThreadSafe
{
    private static readonly object _locker = new object();
    private static Bitmap _snapshot;

    public static Bitmap GetSnapshot(int width, int height)
    {
        lock (_locker)
        {
            if (_snapshot == null)
                return null;

            return new Bitmap(_snapshot, new Size(width, height));
        }
    }

    public static void SetSnapshot(Bitmap source, int width, int height)
    {
        var copy = new Bitmap(source, new Size(width, height));
        lock (_locker)
        {
            if (_snapshot != null)
                _snapshot.Dispose();
            _snapshot = copy;
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top