Initialize Watermaker in multi threads using .NET

Hi:
I have two DOC files with file sizes of 300MB and 9KB.
When I used the two files in separate threads to initialize instances of Watermarker, the time between the two threads was close. There seems to be a lock in the Watermarker.
The code is:

using GroupDocs.Watermark;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace WatermarkDemo
{
    internal class Program
    {
        static string bigFileName = "big_file.doc";
        static string smallFileName = "small_file.doc";

        static void Main(string[] args)
        {
            InitWatermarkerSingleThread();

            Console.WriteLine("------------------");

            InitWatermarkerMultiThreads();

            Console.WriteLine("------------------");

            Console.WriteLine("All threads has completed.");
        }

        static void InitWatermarkerSingleThread()
        {
            InitWatermarker(bigFileName);
            InitWatermarker(smallFileName);
        }

        static void InitWatermarkerMultiThreads()
        {
            var t1 = new Thread(() =>
            {
                InitWatermarker(bigFileName);
            });

            var t2 = new Thread(() =>
            {
                InitWatermarker(smallFileName);
            });

            t1.Start();
            t2.Start();

            t1.Join();
            t2.Join();
        }

        static void InitWatermarker(string fileName)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                Watermarker watermarker = new Watermarker(stream);
            }

            stopwatch.Stop();

            Console.WriteLine($"Init {fileName} take {stopwatch.ElapsedMilliseconds}ms");
        }
    }
}

The output is:
image.png (2.6 KB)

Product Version: GroupDocs.Watermark for NET 23.7.1
OS: Windows 10

I hope for your answer.
Thank you very much.
Best regards.

@caoyanmin

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): WATERMARKNET-1464

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

@caoyanmin

We are pleased to announce that the issue you described has been fixed in GroupDocs.Watermark release 24.1. We have reworked the initialization of the Watermarker class and significantly improved its speed. This will be noticeable not only in a multi-threaded example, but even if you simply compare the initialization time of your 300MB Word document in previous versions and version 24.1.

1 Like

The GroupDocs.Watermark 24.1 depend on System.Drawing.Common 6.0, when I add watermark to a Excel on Linux, there was a exception like below:

Unhandled exception. System.TypeInitializationException: The type initializer for 'Gdip' threw an exception.
 ---> System.PlatformNotSupportedException: System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information.
   at System.Drawing.LibraryResolver.EnsureRegistered()
   at System.Drawing.SafeNativeMethods.Gdip.PlatformInitialize()
   at System.Drawing.SafeNativeMethods.Gdip..cctor()
   --- End of inner exception stack trace ---
   at System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0(Int32 width, Int32 height, Int32 stride, Int32 format, IntPtr scan0, IntPtr& bitmap)
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
   at .(String , Font , Thickness )
   at GroupDocs.Watermark.Watermarks.TextWatermark.d6j8hma6hg6ubbavbtg9zghtays3vwqh

t .()
   at .()
   at.(Shape , Watermark ,  )
   at .(TextWatermark , SpreadsheetWorksheet ,  )
   at .extWatermark , SpreadsheetWorksheet ,  )
   at atermark , ContentPart ,  )
   at.(ContentPart , Watermark ,  , IDictionaryé2)
   at.(ContentPart , Watermark ,  , IDictionaryé2)
   at.ontentPart , Watermark ,  )
   at GroupDocs.Watermark.Contents.ContentPart.zeumdk2eqe4dcdkfe89auyve5hpn4u5vatermark )
   at GroupDocs.Watermark.Contents.Spreadsheet.SpreadsheetContent.pt554w7rscmvuffupxrvruxuc9hecqqtatermark , WatermarkOptions )
   at GroupDocs.Watermark.Watermarker.Add(Watermark watermark, WatermarkOptions options)
   at GroupDocs.Watermark.Watermarker.Add(Watermark watermark)
   at WatermarkDemo.Program.InitWatermarker(String fileName, String output)
   at WatermarkDemo.Program.Main(StringÄÅ args)

@caoyanmin

For applications that must run on Linux, you can install libgdiplus , which is a GDI+ compatible API on non-Windows platforms.

sudo apt-get update
sudo apt-get install -y libgdiplus

Let us know if issue persists.

It doesn’t work properly, it seems that System.Drawing.Common doesn’t support running on Linux.

Setting System.Drawing.EnableUnixSupport to true can temporarily resolve this issue.

1 Like

@caoyanmin

Good to know that the issue is resolved.
However, we are investigating (if there can be a permanent solution) this scenario at our end as well. Your investigation ticket ID is WATERMARKNET-1645.

@caoyanmin

This is a well known scenario of using System.Common.Drawing library in the .Net 6.
So, the right solution in .NET 6 is to enable System.Drawing.EnableUnixSupport setting as shown here.
or another option to add line

<RuntimeHostConfigurationOption Include="System.Drawing.EnableUnixSupport" Value="true" />

in the .csproj file.

Additionally, we have plans to migrate API from using System.Drawing.Common to another cross-platform drawing library, like Microsoft suggests here Breaking change: System.Drawing.Common only supported on Windows - .NET | Microsoft Learn, but currently we can’t provide estimation when this will be done.