PSA: GenerateNewLotNum is NOT thread safe.. will duplicate

Ok, I put in a new system last week, where all my report qty is automated, lotnumber generation etc, all nice and tidy. It’s sweet…

However, I started to have some issues.

We have all of our parts assigned to a global lot sequence.
We assumed this would always be unique. We assumed wrong.

Just so happens, when reporting multiple items at a time, from different threads, GenerateNewLotNum will return the same lot number.

We need it all to be unique lol.

We switched over to GetNextSequence for lot number generation, and all is well.
This also eliminates when our engineering dept forgets to assign the global lot sequence, as it is irrelevant.

6 Likes

What version did you install as there is a known bug with Get Next Lot on Global Lot Sequence that was fixed in 2025.2.12 (Supposedly).

3 Likes

2025.2.10

2 Likes

Forgive me, but I had to have ChatGPT remind me a bit how to use a mutex, but you can work around the original problem with GenerateNewLotNum with code similar to the following:

try
{
    const string mutexName = "MySuperSpecialMutext";

    using (var mutex = new Mutex(false, mutexName))
    {
        var lockTaken = false;

        try
        {
            try
            {
                lockTaken = mutex.WaitOne(TimeSpan.FromSeconds(30));
            }
            catch (AbandonedMutexException)
            {
                // Another thread/process died while holding it.
                // You still acquire the mutex here.
                lockTaken = true;
            }

            if (!lockTaken)
            {
                throw new TimeoutException("Could not acquire mutex.");
            }

            string partNum1 = "099965-0300-002";
            string partNum2 = "046000-0200-003";

            // NonThreadSafeMethod();
            CallService<Erp.Contracts.LotSelectUpdateSvcContract>(lsu =>
            {
                string lotNum = "";

                for (int i = 0; i < 1000; i++)
                {
                    string pn = i % 2 == 0 ? partNum1 : partNum2;

                    lsu.GenerateNewLotNum(pn, out lotNum);

                    var ts = new LotSelectUpdateTableset();

                    lsu.GetNewPartLot(ref ts, pn);

                    ts.PartLot.FirstOrDefault().LotNum = lotNum;

                    lsu.Update(ref ts);

                    Message += lotNum + Environment.NewLine;
                }
            });
        }
        finally
        {
            if (lockTaken)
            {
                mutex.ReleaseMutex();
            }
        }
    }
}
catch (Exception ex)
{
    Message += ex.Message;
}

I ran this from two different clients simultaneously.
I took the output and put it in excel, all unique lots.

It was all jacked up before lol without the mutex.

6 Likes

On 2025.2 they are auto generating lot numbers for part specific lots and attaching it to the LaborDtl record. To get the next lot you have to end activity and start again. It’s possible that might be playing a role? Not sure if GenerateNewLotNum might be giving you the same number based on that?

2 Likes

Interesting… How’d you come across that?

Thanks for the heads up.

Came across it because we were auto reporting qty from jobs and it kept failing after the upgrade. It was because the BO wanted lot attributes and I wasn’t giving them for end activity, because well frankly they shouldn’t exist. I’m not sure what special use case they were accounting for but one Lot number per LaborDtl seems an oddly specific feature.

2 Likes

Seems odd for sure, maybe tracking nonconformance or scrap?