Author Topic: Problems with eLockViolations... Among other things  (Read 6681 times)

0 Members and 1 Guest are viewing this topic.

Nutse

  • Guest
Problems with eLockViolations... Among other things
« on: July 02, 2013, 06:17:57 AM »
Hello all, new user here, and I have what I hope is a simple (stupid?) question.

I'm working on a tool to convert dwg's from one applications format to another, mainly by reading Attributes/Xdata and writing those data back to the symbol in another Attribute/XData based on custom rules.

We use a WCF Service to communicate with AutoCAD, which seems to work pretty good most times, but now to my problem.

I write for example Attribute data to the symbol calling the following function:

Code: [Select]
public void SetSymbolData(string handle, string tag, string value)
{
if (host.Document != null && host.Document.Name != null)
{
using (DocumentLock docLock = host.Document.LockDocument())
{
long ln = Convert.ToInt64(handle, 16);
Handle hn = new Handle(ln);
ObjectId id = new ObjectId();
if (host.Document.Database.TryGetObjectId(hn, out id))
{
using (Transaction tr = host.Document.Database.TransactionManager.StartTransaction())
{

BlockReference blk = tr.GetObject(id, OpenMode.ForWrite) as BlockReference;
if (blk != null)
{
foreach (ObjectId arId in blk.AttributeCollection)
{
DBObject obj = tr.GetObject(arId, OpenMode.ForRead);

AttributeReference ar = obj as AttributeReference;
if (ar != null)
{
if (ar.Tag == tag)
{
ar.UpgradeOpen();
ar.TextString = value;
break;
}
}
}
AttributeReference attRef = new AttributeReference();
attRef.Tag = tag;
attRef.TextString = value;
blk.AttributeCollection.AppendAttribute(attRef);
tr.AddNewlyCreatedDBObject(attRef, true);
}
tr.Commit();
}
}
}
}
}
}

private IdesAcadServiceHost host
{
get
{
return OperationContext.Current.Host as IdesAcadServiceHost;
}
}

Sometimes this works beautifully, not a problem at all... But then sometimes it crashes giving me an eLockViolation when the Document Lock disposes. It seems to me that I get this error whenever I move the mouse over the drawing...

It might be that I'm way off in how I should do this, but I'm hoping that you might have som pointers for me.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Problems with eLockViolations... Among other things
« Reply #1 on: July 02, 2013, 02:07:43 PM »
Are you able to share more details on the implementation of IdesAcadServiceHost?  I suspect the issue is under there.

Nutse

  • Guest
Re: Problems with eLockViolations... Among other things
« Reply #2 on: July 03, 2013, 03:13:40 AM »
It's more or less a standard ServiceHost, we only added a property for the Document.

Code: [Select]
class IdesAcadServiceHost : ServiceHost
    {
        public Document Document { get; set; }

        public IdesAcadServiceHost(Type serviceType, Uri baseAddress, Document doc)
            : base(serviceType, baseAddress)
        {
            Document = doc;
        }
    }

The servicehost is created in the Initialize method of one of our bundles.

Code: [Select]
serviceHost = new IdesAcadServiceHost(typeof(IdesAcadService), baseAddress, AcadApp.DocumentManager.MdiActiveDocument);
It's all rather basic, and the weird thing is that it does work fine a lot of times.
If I run my Conversion and do nothing, it works fine. If I move the mouse-pointer (no clicking, just moving) around over the drawing while the conversion takes place, I will get a crash. Since I use the service I dont really get any good information except that the pipe's not working anymore, however when I've debugged I've seen the eLockViolation exceptions I mentioned in my first post.

Nutse

  • Guest
Re: Problems with eLockViolations... Among other things
« Reply #3 on: July 03, 2013, 06:11:00 AM »
Just thought of two things that might be useful:

1. I'm working with AutoCAD 2013

2. I added IncludeExceptionDetailInFaults=true to my service just to see if I could get more error information, and if I have my mouse pointer over the drawing I get the following:

Quote
"System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: eLockViolation (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
Autodesk.AutoCAD.Runtime.Exception: eLockViolation
   at Autodesk.AutoCAD.ApplicationServices.DocumentLock.~DocumentLock()
   at Autodesk.AutoCAD.ApplicationServices.DocumentLock.Dispose()
   at Ides.Providers.AutoCAD.Common.Services.IdesAcadService.SetSymbolData(String handle, Int32 type, String tag, String value)
   at SyncInvokeSetSymbolData(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet))."


Jeff H

  • Needs a day job
  • Posts: 6150
Re: Problems with eLockViolations... Among other things
« Reply #4 on: July 03, 2013, 08:39:03 AM »
So in the finalizer of LockDocument.
 
 
To make it easier for others
Code - C#: [Select]
  1.        public void SetSymbolData(string handle, string tag, string value)
  2.        {
  3.            if (host.Document != null && host.Document.Name != null)
  4.            {
  5.                using (DocumentLock docLock = host.Document.LockDocument())
  6.                {
  7.                    long ln = Convert.ToInt64(handle, 16);
  8.                    Handle hn = new Handle(ln);
  9.                    ObjectId id = new ObjectId();
  10.                    if (host.Document.Database.TryGetObjectId(hn, out id))
  11.                    {
  12.                        using (Transaction tr = host.Document.Database.TransactionManager.StartTransaction())
  13.                        {
  14.                            BlockReference blk = tr.GetObject(id, OpenMode.ForWrite) as BlockReference;
  15.                            if (blk != null)
  16.                            {
  17.                                foreach (ObjectId arId in blk.AttributeCollection)
  18.                                {
  19.                                    DBObject obj = tr.GetObject(arId, OpenMode.ForRead);
  20.                                    AttributeReference ar = obj as AttributeReference;
  21.                                    if (ar != null)
  22.                                    {
  23.                                        if (ar.Tag == tag)
  24.                                        {
  25.                                            ar.UpgradeOpen();
  26.                                            ar.TextString = value;
  27.                                            break;
  28.                                        }
  29.                                    }
  30.                                }
  31.                                AttributeReference attRef = new AttributeReference();
  32.                                attRef.Tag = tag;
  33.                                attRef.TextString = value;
  34.                                blk.AttributeCollection.AppendAttribute(attRef);
  35.                                tr.AddNewlyCreatedDBObject(attRef, true);
  36.                            }
  37.                            tr.Commit();
  38.                        }
  39.                    }
  40.                }
  41.            }
  42.        }
  43.    
  44.         private IdesAcadServiceHost host
  45.         {
  46.         get
  47.         {
  48.         return OperationContext.Current.Host as IdesAcadServiceHost;
  49.         }
  50.  

Nutse

  • Guest
Re: Problems with eLockViolations... Among other things
« Reply #5 on: July 03, 2013, 08:43:32 AM »
Correct... Sorry about the code formatting, haven't quite gotten the hang of the forums features yet...

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Problems with eLockViolations... Among other things
« Reply #6 on: July 03, 2013, 11:06:32 AM »
I'm wondering what context you're calling this from in your application if that may be causing the issue.

Try using the overloaded LockDocument( DocumentLockMode.ProtectectedAutoWrite, null, null, false )

Nutse

  • Guest
Re: Problems with eLockViolations... Among other things
« Reply #7 on: July 03, 2013, 11:52:09 AM »
I've been trying a few different overloads of LockDocument, both ProtectedAutoWrite and ExclusiveWrite, but so far no luck :/

I'm calling from an external application, so the lock is definately needed. The thing that is so weird is that we only get the exception when AutoCAD is handling mouse movement...

I'm going to try to make a new simple application to see if I can replicate the problem, if so I could upload a sample project...

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Problems with eLockViolations... Among other things
« Reply #8 on: July 03, 2013, 12:43:54 PM »
Try doing the work on a Application.Idle event handler, it should save you from this issue.

n.yuan

  • Bull Frog
  • Posts: 348
Re: Problems with eLockViolations... Among other things
« Reply #9 on: July 03, 2013, 01:09:08 PM »
I've been trying a few different overloads of LockDocument, both ProtectedAutoWrite and ExclusiveWrite, but so far no luck :/

I'm calling from an external application, so the lock is definately needed. The thing that is so weird is that we only get the exception when AutoCAD is handling mouse movement...

I'm going to try to make a new simple application to see if I can replicate the problem, if so I could upload a sample project...

So, the AutoCAD session is used like a server hosting a WCF service that is called from your external app. Are you saying that while the AutoCAD session sitting there to serve external calls, someone also use the same AutoCAD session, moving mouse around or even drawing something in the same AutoCAD session?

It just like 2 users are trying to use 1 AutoCAD session: they cannot do things with the same AutoCAD session spondaneously, they have to do things one after another (that is, to AutoCAD session, there is only one user doing things at a time).

Even moving mouse around, there may be a lots of activities going. For example, when hovering mouse on some entity, built-in or custom tooltip may require to lock document and retrieve entity information for the tooltip... You cannot just simply assume the external calling to the Acad hosted services can always lock the document whenever it wants (well, unless you are absolutely the external app is the only thing touches the AutoCAD session, once at a time). Even AutoSaving called by AutoCAD would reject your WCF client's locking document request.

As Will's suggestion, you may have to find a way to utilize Application.Idle event to materialize your external call. Or, at least your code handles locking document error, and retrying.

No matter what you do, having user and external app competing the same AutoCAD session is not good idea at all; having multiple WCF clients to call services hosted in the same AutoCAD session directly would also be problematic.

Nutse

  • Guest
Re: Problems with eLockViolations... Among other things
« Reply #10 on: July 03, 2013, 02:14:21 PM »
The external application in question is our main application, we develop a tool for among other things electrical design, where we use AutoCAD as the CAD platform. When we perform the process in question here we dont use the AutoCAD for anything else but the drawing conversions, however we cannot stop the user from i.e. moving the mouse around the screen.

I will look into Application.Idle event handler to see if I can find any way out of this.

Quote
You cannot just simply assume the external calling to the Acad hosted services can always lock the document whenever it wants (well, unless you are absolutely the external app is the only thing touches the AutoCAD session, once at a time). Even AutoSaving called by AutoCAD would reject your WCF client's locking document request.

So you mean that the lock I make from my external application will be overriden by "internal" locks? This is what it seems like since the errors I get are when I try to dispose my lock.
« Last Edit: July 03, 2013, 02:23:46 PM by Nutse »

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Problems with eLockViolations... Among other things
« Reply #11 on: July 03, 2013, 03:12:06 PM »
So you mean that the lock I make from my external application will be overriden by "internal" locks? This is what it seems like since the errors I get are when I try to dispose my lock.

Could also be that your lock is failing to begin with because the document is already locked by the application.  What does the Document.LockMode() method return before and after you try to lock it?
Check if your lock is null before dispose, does this happen?

Perhaps worth noting: you can use Editor.WriteMessage() to spit out useful debug data since you're using a service.  A useful pattern is
Code - C#: [Select]
  1. try
  2. {
  3.    //code
  4. }
  5. catch (System.Exception e)
  6. {
  7.     Application.DocumentManager.MDIActiveDocument.Editor.Writemessage(e.toString());
  8. }

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Problems with eLockViolations... Among other things
« Reply #12 on: July 05, 2013, 10:10:19 PM »
Only tested very little but something to put transaction and locking a document together
Code - C#: [Select]
  1.    public class LockedTransaction : Transaction
  2.     {
  3.        DocumentLock docLock;
  4.        public LockedTransaction(Transaction trx, DocumentLock docLock)
  5.            : base(trx.UnmanagedObject, trx.AutoDelete)
  6.        {
  7.            Interop.DetachUnmanagedObject(trx);
  8.            GC.SuppressFinalize(trx);
  9.            this.docLock = docLock;
  10.        }
  11.        protected override void Dispose(bool A_1)
  12.        {
  13.            base.Dispose(A_1);
  14.            if (A_1)
  15.            {
  16.                docLock.Dispose();
  17.            }
  18.        }
  19.     }
  20.  .........
  21. //////TransactionManager defined in ApplicationServices namespace
  22.        public static LockedTransaction StarLockedTransaction(this TransactionManager tm)
  23.        {
  24.            DocumentLock doclock = Application.DocumentManager.MdiActiveDocument.LockDocument();
  25.            return new LockedTransaction(tm.StartTransaction(), doclock);
  26.        }
  27.