Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling image.WriteToBuffer in parallel with a shared VOption leads to exception (solution included) #228

Closed
korkmazad opened this issue Mar 1, 2024 · 2 comments
Labels
bug Something isn't working
Milestone

Comments

@korkmazad
Copy link

korkmazad commented Mar 1, 2024

When we call image.WriteToBuffer with a shared VOption, we receive an error:

Problematic:(Run in parallel)

var option = new VOption() { { "Q", JpegQuality } };
using var thumb = image.ThumbnailImage(250);
var thumbData = thumb.WriteToBuffer(".jpg", option);
thumb.Close();

Works:

using var thumb = image.ThumbnailImage(250);
var thumbData = thumb.WriteToBuffer(".jpg", new VOption() { { "Q", JpegQuality } });
thumb.Close();

Message:

at System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException[T](T key)
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at NetVips.ExtensionMethods.Merge(VOption self, VOption merge)
   at NetVips.Image.WriteToBuffer(String formatString, VOption kwargs)

So the cause and the possible fixes:

  1. Image.WriteToBuffer calls kwargs.Merge with the stringOptions
  2. ExtensionMethods.Merge calls VOption[key] = value;
  3. This calls VOption's this[string key]'s set method:
{
    get => _internalDictionary[key];
    set => Add(key, value);
}
  1. Which then calls this:
    public void Add(string key, object value) => _internalDictionary.Add(key, value);
    The problem with dictionary.Add is, non-repeatability.
    We use a workaround in our code now while calling.

But in the code there are 2 easy solution options:

  1. Change VOption.Add to Add(string key, object value) => _internalDictionary[key] = value;
  2. Add a new method called Set(string key, object value) => _internalDictionary[key] = value;
    and call it from set => Set(key, value);
@kleisauke kleisauke added the bug Something isn't working label Mar 9, 2024
@kleisauke kleisauke added this to the 2.4.1 milestone Mar 9, 2024
kleisauke added a commit that referenced this issue Mar 9, 2024
The set accessor of the `VOption` indexer property was incorrectly implemented.
@kleisauke
Copy link
Owner

Commit 7b723e3 should fix this. Thanks for reporting this!

If you want to test this, you can use the nightly version of NetVips. Add the https://ci.appveyor.com/nuget/net-vips feed in the <packageSources> section of your NuGet.config:

<packageSources>
  <add key="netvips-nightly" value="https://ci.appveyor.com/nuget/net-vips" />
</packageSources>

And update NetVips to 2.4.0 (build number 527 - prerelease). I'll make a new release soon.

@kleisauke
Copy link
Owner

NetVips v2.4.1 is now available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants