Is NAS multithread?


I always thought that NAS is not multithread, but now I have real situation, which is strange and can only be possible with two processes running in one time (or at least not waiting until all code of previous process is finished).
I have two timers on one NAS instance. One timer is posting Sales Invoices. Another timer is executing Job Scheduler jobs. When on job scheduler “Post Inventory Cost to GL” job is running and Sales Invoices are posting in same time, inventory cost posting stops with error that GL entry 7489385 already exist and (what is very strange) two posted GL entries I can find in database – they where commited, but I can‘t find commit in this procedure.
In GL register I can find following entries:
No. Creation Date User ID Source Code From Entry No. To Entry No.
987166 11/09/2007 NAS_USER SALES 7489362 7489368
987167 11/09/2007 NAS_USER SALES 7489369 7489375
987168 11/09/2007 NAS_USER SALES 7489376 7489382
987169 11/09/2007 NAS_USER INVTPCOST 7489383 7489384
987170 11/09/2007 NAS_USER SALES 7489385 7489391
987171 11/09/2007 NAS_USER SALES 7489392 7489396
987172 11/09/2007 NAS_USER SALES 7489397 7489403
987173 11/09/2007 NAS_USER SALES 7489404 7489412
987174 11/09/2007 NAS_USER SALES 7489413 7489419

It seems, that Inventory Cost Posting procedure locked GL Entry, posted two entries and in some moment another process started, locked GL Entry (it was allowed, because process ID in SQL is the same), posted sales invoice, commited all entries (also posted by another process, because commit runs on SQL for all entries created by SQL process ID), then Cost Posting procedure tried to insert next entry and got error. Is it possible that it happened in such way?

NAS is NOT multithread!

I think something else happened:

Or you post using something as cduSomeCodeunit.SomeFunction(…) and running this multiple times. Before doing this, you should do a CLEAR( cduSomeCodeunit).

But more probably this happened:

You have a IF codeunit.RUN(…) THEN BEGIN


If you have an error when posting and something has been written to the DB, with the IF codeunit.RUN THEN, those writings are NOT undone!!!

So after the test, you continue with other things, but your half-posted invoice remains there.

So to fix it, you should let Navision go in Error and then restart with the help of the Navision-Timer.

I do not use IF THEN commmands. I use TimmerError trigger to get the error and save it to log entry.

Both timers are on different codeunits, so they have different variables and I don’t think, that not clearing some codeunit variable could cause such effect.

In any case problem is when I run Post Inventory Cost to GL report - it is standart report, it inserts two GL entries, but on inserting third entry it gets error that entry already exists.

Some questions:

-which version of Navision do you use?

-are the objects for “post inventory cost to GL” W1, localized or customized?

-If you are running the “post inventory cost to GL” manually, do you have the same problem

-Can you post the code with the TimerError-trigger so we can take a look at it?

  • Version is 4.02 database / 4.03 executable

  • Objects are mostly standard. There are only minor changes: in report Post Inventory Cost to G/L only parameters are passed from job scheduler and status bar is hided. In codeunit Inventory Posting To G/L only some GL acount assignes are updated.

  • Running Post Inventory Cost to G/L mannually or automatically (when another timer is not doing postings), I don’t have problems.

  • In both timers TimerError triggers there is code similar to this one:

LogEntry.“Error Description” := COPYSTR(ErrorString,1,250);
LogEntry.Erroneous := TRUE;

Use a client to run the jobs automatically. Enable the debugger (but no breakpoint on triggers). Wait until an error comes up and then go step-by-step to see what happens.

After error system goes to TimmerError trigger.

Question is why Cost Posting procedure was interrupted in the middle of process and I don’t think, that it is possible to catch that with debugger.

If it is an error, it should catch it. That is the reason I said to use a client to launch the NAS-routines. It is a lot easier to debug.

I understand what you mean. I current situation I get error at the very end and debugger will not help. Maybe it is possible to do that, but for that I need to force error on Invoice posting timer. I tried to create similar situation on testing DB running codeunits with normal client, but I couldn’t force to interrupt Cost posting procedure…

After more detailed investigations I can say that NAS is not multithread, because looking to both timers logs, I can see that when one timer is processing, another is waiting:

Timer 1 Timer 2
Post Inventory Cost to GL started on 05:38:09.747
Inserted two GL entries
Sales Invoice Posting started on 05:38:11.447
Finished invoicing on 05:52:26.767
Continued Post Inv. to GL
Error that GL entry exists on 05:52:29.577

Problem is that Cost Posting is always interrupted by another timer. It doesn’t happens with other functions. I am still trying to find out why…