Unloading external DLL library after 10 seconds in order to release file locks In my web application, I'm utilizing a PDF library which is using a native DLL.

I'm using it for two very different purposes in two completely separate (and isolated by NuGet) parts of the web application.

Upon application start, I load the library DLL and thus lock the file. Then, rebuild requires completely terminating the application which takes much time and disrupts our workflow.

We cannot load and unload the DLL on every operation, as the operation will be executed lots of times in bursts. This will also not be thread safe.

So in order to alleviate this, I have decided to make a small wrapper to the PDF library that:


for every operation (it will only have 2) it will check if the library is loaded.
If not, it loads it. After the operation, it sets a timer that will unload the DLL in, let's say 10 seconds.
If another operation is executed within this timeframe, the timer is reset.


This is the code I have written so far to achieve this, appreciate any pointers.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace PdfLibrary
{
    public static class PdfLibrary
    {
        static object Lock = new object();
        static TimeSpan Timeout = new TimeSpan(0, 0, 10);
        static bool IsLoaded = false;
        static Timer UnloadTimer = new Timer();

        static PdfLibrary()
        {
            UnloadTimer.Interval = Timeout.TotalMilliseconds;
            UnloadTimer.Elapsed += (_, __) =&gt; Unload();
        }

        private static void Unload()
        {
            UnloadTimer.Stop();

            lock (Lock)
            {
                // ... unloads pdf library ...
            }
        }

        static void DoWhenLoaded(Action action)
        {
            if (!IsLoaded)
            {
                lock (Lock)
                {
                    if (!IsLoaded)
                    {
                        // ... loads pdf library ...
                    }
                }
            }

            action();

            UnloadTimer.Stop();
            UnloadTimer.Start();
        }

        public static IEnumerable&lt;string&gt; ExtractText(Stream inputStream)
        {
            IEnumerable&lt;string&gt; result = null;

            DoWhenLoaded(() =&gt; {
                // ... sets result ...
            });

            return result;
        }
    }
}
Another, perhaps simpler, option is to locally copy the dll and load the copy. 

Then regularly check the original dll for an updated last modified time and then unload the copied dll, make a fresh copy and load the new copy.

Do keep in mind that when debugging a dll has a pdb file associated with it and loading the dll also locks the pdb. You can work around that by making the compiler emit the pdb with a different name each time.



However as is your implementation isn't thread safe. If the timer is about to trigger then action could still be running. Instead you will want to use a ReaderWriterLock, take a read lock when doing action() and a write lock when actually loading and unloading.

Lock.AcquireReaderLock(1000);
try{
    if (!IsLoaded)
    {
        LockCookie cookie = Lock.UpgradeToWriterLock(1000);
        try {
            //someone else may have gotten ahead in the queue
            if (!IsLoaded)
            {
                // ... loads pdf library ...
            }
        } finally {
            Lock.DowngradeFromWriterLock(cookie);
        }
    } 
    action();

} finally {
    Lock.ReleaseReaderLock();
}