ERROR: System.Runtime.InteropServices.COMException (0x8001010A): The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))
at AutoCAD.IAcadDocument.SendCommand(String Command)
at BOM_CALCS.LaunchAutoCAD.StartAutoCAD() in C:\Engineering\Calculations\BOM\BOM_CALCS\LaunchAutoCAD.cs:line 55
at BOM_CALCS.Program.Main(String[] args) in C:\Engineering\Calculations\BOM\BOM_CALCS\Program.cs:line 102
Unfortunately the 3-4 times per day has now grown to 10-12 times per day. There's not much in the way of help for this because it's intermittent. And the same code that runs perfect all other times hits this enough for it to be of concern.< .. >Code: [Select]ERROR: System.Runtime.InteropServices.COMException (0x8001010A): The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))
at AutoCAD.IAcadDocument.SendCommand(String Command)
at BOM_CALCS.LaunchAutoCAD.StartAutoCAD() in
C:\Engineering\Calculations\BOM\BOM_CALCS\LaunchAutoCAD.cs:line 55
at BOM_CALCS.Program.Main(String[] args) in
C:\Engineering\Calculations\BOM\BOM_CALCS\Program.cs:line 102
... he thinks the problem is a COM object being left un-closed.....
< .. >
The tricky thing about this is that it has seen days, weeks, on end when it works perfectly. A very experienced developer was hired recently and he introduced an RPC service into the mix. This is when I started noticing the problem.
< .. >
using System;
using AutoCAD;
namespace AHD_BOM_CALCS
{
class LaunchAutoCAD
{
private static IAcadApplication vAcadApp = null;
private static IAcadDocument vAcadDoc = null;
// CHANGE THIS TO AutoCAD.Application.20 FOR ACAD 2015/16
private static string vAcadID = "AutoCAD.Application.20";
private static string LispPath = @"C:/Engineering/04VLISP/ANGLE/Bomber/";
private static string DwgPath = @"C:\Engineering\09Automated Drawings\";
public static void StartAutoCAD()
{
try
{
// Check for instance of AutoCAD
vAcadApp = (IAcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject(vAcadID);
}
catch (Exception) // If none found start a new instance of AutoCAD
{
System.Type AcadProg = System.Type.GetTypeFromProgID(vAcadID);
vAcadApp = (IAcadApplication)System.Activator.CreateInstance(AcadProg);
}
string titleblock = "Template1(Automated).dwg";
if (vAcadApp != null)
{
vAcadApp.Visible = true;
vAcadDoc = vAcadApp.Documents.Open(DwgPath + titleblock, true);
string LispName = "Bomber.lsp";
vAcadDoc.SendCommand("(load \"" + LispPath + LispName + "\" \"The load failed\") ");
vAcadDoc.SendCommand(LISPVariables.PrepareAcadCmd() + " ");
vAcadDoc.SendCommand("(setvar \"osmode\" 703) ");
vAcadDoc.SendCommand("(setvar \"cmdecho\" 1) ");
vAcadDoc.SendCommand("(setvar \"pickbox\" 5) ");
vAcadDoc.SendCommand("(setq svPath \"C:/0/Misc/BomberDevDwgs/\") ");
vAcadDoc.SendCommand("(setq *erp 1) ");
vAcadDoc.SendCommand("DrawitNow ");
}
else
{
Console.WriteLine("ERROR: The drawing file is missing.");
Console.ReadKey();
}
}
}
}
Why using sendCommand since you can call or change the system variable via the application?
e.g;Code - C#: [Select]
Application.SetSystemVariable("OSMODE", 0);
Opps, Sorry I did not notice that.Why using sendCommand since you can call or change the system variable via the application?
e.g;Code - C#: [Select]
Application.SetSystemVariable("OSMODE", 0);
Don't think that would work from outside of an AutoCAD executed program.
Since it's tripping up at the SendCommand() area, you can try removing some of the commands. Do these three really need to be set within the C# section of code? It would be quite easy and clean to run them in the beginning of your lisp routine.Code - C#: [Select]
vAcadDoc.SendCommand("(setvar \"osmode\" 703) "); vAcadDoc.SendCommand("(setvar \"cmdecho\" 1) "); vAcadDoc.SendCommand("(setvar \"pickbox\" 5) ");Code - Auto/Visual Lisp: [Select]
Why using sendCommand since you can call or change the system variable via the application?
e.g;Code - C#: [Select]
Application.SetSystemVariable("OSMODE", 0);
Don't think that would work from outside of an AutoCAD executed program.
Why using sendCommand since you can call or change the system variable via the application?
e.g;Code - C#: [Select]
Application.SetSystemVariable("OSMODE", 0);
Don't think that would work from outside of an AutoCAD executed program.
Well, the OP's code has already obtained the AcadApplication object, it can certainly be done (and should be done):
vAcadApp.SetSystemVariable(...)
instead of SendCommand(), which is likely the cause of his problem.
https://msdn.microsoft.com/en-us/library/ms228772.aspxBy George, I think you've got something there. However, after the reboot, the project has just made 15 successful consecutive runs. Turns out the tech who told me he rebooted it last week was confusing it with another machine. So to avoid confusion I went into the cold room and rebooted it myself. Now, I'm not saying that a reboot fixed it but it's running better than it was. And looking into that article you referenced our .NET guru and myself are going to look into that further. In any case, I think now the overseers are a little more understanding that it's not the C# code itself, and it's especially not the LISP code. Rather it does appear to be a conflict between Visual Studio and a multi-threaded app like AutoCAD...
Using full desktop AutoCAD as a non-user-interactive server app is problematic, to say the least. Especially your code try to use the same instance of AutoCAD session (the code first tries to find existing AutoCAd session, and only start a new session of no existing one is obtained), which is particular bad practice when using AutoCAD as "server" (plus, multiple SendCommand() calls that could be executed out of sync makes thing even worse). Even you can claim it had worked for quite a while, it was mostly out of good luck (low work load), IMO.Yes, I agree with all that you said. However, the nature of this project means that several requests may hit simultaneously. Let me elaborate on that if I may. In this setup we use a Load Balancing server which sends requests to one of two identical Windows 7 machines running Apache+php and AutoCAD 2016 Mechanical. AutoCAD is loaded and sitting there with no drawing open all the time. Presently, and due to all the code changes happening at this stage, we let one of them sleep and the other works all day but eventually we will turn both of them on and it can handle the load, even with 200-300 requests per 8 hour shift. I have seen just one of these boxes handle up to three instances successfully without a problem. But when a 4th one hits, it's a no-go and AutoCAD just chokes on it all. And it's not foreseen that even under the heaviest loads that we would put on it, two machines will be more than adequate.
If you have to use AutoCAD as server, it would be better to start a new AutoCAD session, build one drawing and then close the AutoCAD session. Just imagine, when drawing building is in progress, and since the process need to get data from somewhere (Oracle DB, as you mentioned) outside the process, and you never know what could happen and the process has to wait the data come back. So, the drawing building process could be long or short. If then a nother request comes in and you code luckily find the existing AutoCAD session and tries to hold it for new request while the existing AutoCAd session is still working on previous request... Your app now may be in a "dead lock" state.
Depending on your workload, running multiple AutoCAD session in the same computer may also be problematic, of course, because AutoCAd desktop app is such a "resouces" hangry beast.
You should consider to use AutoCAD console for this type of work instead of full AutoCAD.
AutoCAD is NOT multi-threaded (in fact, you can't do that with AutoCAD customization at all) except for a couple of parts which don't/shouldn't have any relevance here.Aha, I was not aware of that. I thought it was. Shows how much I know.
There is even talk of getting rid of AutoCAD all together and use some other kind of rendering engine, but I've warned them that how do you send a client an AutoCAD file if there is no AutoCAD to produce it.
You can bypass AutoCAD loading, kind ofConfirmed. If you think the Docs on AutoCAD .NET are ... well, you know ... you should see the docs for their lesser-used platform. Building the installer is a nightmare, there's no pre-fab solution as such. I hope you know and love Wix. I assume building an installer for Teigha stuff is just as tricky.
http://www.techsoft3d.com/products/autodesk-platforms/realdwg/
For the price it's pretty haphazardly put together but an option.
I believe parts of the rendering engines are multi-threaded but the Database engine definitely isn't. You can run background threads for things unrelated to Database access but everything for Database access must run on the UI thread.AutoCAD is NOT multi-threaded (in fact, you can't do that with AutoCAD customization at all) except for a couple of parts which don't/shouldn't have any relevance here.Aha, I was not aware of that. I thought it was. Shows how much I know.
https://knowledge.autodesk.com/support/autocad/troubleshooting/caas/sfdcarticles/sfdcarticles/Support-for-multi-core-processors-with-AutoCAD.html (https://knowledge.autodesk.com/support/autocad/troubleshooting/caas/sfdcarticles/sfdcarticles/Support-for-multi-core-processors-with-AutoCAD.html)
I used AutoCAD for loads of renderings a few years ago and would watch the renderings progress with each one of the little squares which indicated that one of the cores was being used. When I saw 12 little boxes prepare the rendering I assumed (wrongly I might add) that AutoCAD was an entirely multi-threaded app.
...
If you wanted to scale up you could just rent extra copies of AutoCAD by the month and run them on spare computers.
Agreed. My suggestion was a way to scale with no more development effort. Doing it properly would definitely work better, as you would expect.If you wanted to scale up you could just rent extra copies of AutoCAD by the month and run them on spare computers.
The cost of using something like Teigha isn’t per-seat.
It would probably be an order of magnitude faster, and much cleaner option than using send command