Link to home
Start Free TrialLog in
Avatar of Pber
PberFlag for Canada

asked on

"Attempted to read or write protected memory" using COM automation from a thread

I've created an application that uses some COM automation libraries from Symantec called from threadpools.  For the most part it works like a charm.  I make several calls to various other methods within the same libraries without issues.  One method (in the code below) seems to throw this error randomly.  I've tried my bag of tricks on it, but can't seem to figure out why it is throwing this exception.  The error doesn't always happen either.  It seems to happen randomly.  Sometimes just the first few connections, the next time it might not error at all.

Any ideas?

Here's the error/stack trace:

System.AccessViolationException was unhandled
  Message="Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
  Source="Interop.VProAuto"
  StackTrace:
       at VProAuto.ProtectorAutoClass.get_ImageJobs()
       at BESR.clsBESR.GetJobData(Object Callback) in C:\Documents and Settings\pbernardin\My Documents\Visual Studio 2005\Projects\BESR\v1.0.1\BESR\clsBESR.vb:line 67
       at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
       at System.Threading.ExecutionContext.runTryCode(Object userData)
       at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
       at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)  
Public Sub GetJobData(ByVal Callback As Object)

        Dim oCurrentJob As VProObj.ImageJob
        Dim task As PQSCHEDULERLib.Task
        Dim myJob As New STRUCT_BESRJOB
        Dim AgentStatus As VProObj.AgentStatus
        Dim v2iAuto As VProAuto.ProtectorAuto

        Try
            v2iAuto = New VProAuto.ProtectorAuto
            v2iAuto.Connect(host)
            Try
                AgentStatus = v2iAuto.Status
                myJob.AgentSTATUS = AgentStatus.Description.ToString
                If v2iAuto.LastSystemBackupInterval > 1 Then
                    myJob.Status = False
                Else
                    myJob.Status = True
                End If
            Catch ex As Exception

            End Try

            Try
                For Each oCurrentJob In v2iAuto.ImageJobs '<-- exception throws here
                    Try
                        task = oCurrentJob.Task
                        myJob.Task = task.DisplayName
                    Catch ex As Exception
                        'myJob.AgentSTATUS = "Task: " & ex.Message
                    End Try
                    Try
                        oNetworkLocation = oCurrentJob.Location(oCurrentJob.Volumes(0))
                        myJob.Dest_Path = oNetworkLocation.Path
                        myJob.Dest_UserID = oNetworkLocation.NetworkUser
                    Catch ex As Exception
                        'myJob.AgentSTATUS = ("local: " & ex.Message)
                    End Try
                    Try
                        oOffsiteLocation = oCurrentJob.offsitecopylocations(0)
                        myJob.Offsite_Path = oOffsiteLocation.Path
                        myJob.OffSite_UserID = oOffsiteLocation.NetworkUser
                    Catch ex As Exception
                        'myJob.AgentSTATUS = ("Offite: " & ex.Message)
                    End Try
                Next
            Catch ex As Exception
                myJob.AgentSTATUS = ("General: " & ex.Message)

            End Try
        Catch ex As Exception
            myJob.AgentSTATUS = ex.Message
        End Try
        BESR_Delegate(index, myJob)

    End Sub

Open in new window

Avatar of x77
x77
Flag of Spain image

You need ensure the GetJobData y Jitted before first call from com object.
for that, invokey it  with a null parameter : GetJobData(Nothing)

Public Sub GetJobData(ByVal Callback As Object)
   if Callback is nothing then return


Avatar of Pber

ASKER

Do you mean to call the sub twice.  Once passing it "nothing". Then call it again with my actual callback?
No, you need ensure the callback function is jitted (compiled to machine code).
This is a initialization concept. you need call only one time to this function before the callback assignement.

Then the com object call the function many times.
Avatar of Pber

ASKER

I call the above function from a loop.  I'm looping through all items in a listview and creating a new class for each item and putting them into a threadpool.  I use a delegate sub to marshall the results back to the UI thread.
So in my case, I can have several hundred instances of the class.  So do I do this once before the loop from a separate instance of the class and this will cause it to compile, then loop?
I've attached the loop that does the processing:

        Dim cBESR As clsBESR
        For Each lvitem As ListViewItem In lvAgent.Items
            cBESR = New clsBESR
            cBESR.index = lvitem.Index
            cBESR.host = lvitem.Text
            cBESR.BESR_Delegate = AddressOf JobStatus_Done
            Try
                Interlocked.Increment(threadcount)
                ThreadPool.QueueUserWorkItem(AddressOf cBESR.GetJobData)
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        Next

Open in new window

You can initialize the JobStatus_Done in the shared constructor in the class owner

Class myClass

   shared sub new()
          JobStatus_Done(nothing)
    end sub

    sub JobStatus_Done
        ....
     end sub

         
You can see other common problem with callback at :
   http://stackoverflow.com/questions/2522402
Avatar of Pber

ASKER

Thanks for the help.  It's appreciated.  I tried your suggestion and still no luck.  I am using COM.Interop, so I'm not sure if that last link you provided will help.
Yeah, there are lots of people with this same error. Unfortunately no general solution.
It seems to cause the error on the first few calls, then the rest are ok.  If I run the routine again, it usually doesn't error at all.  The odd time all calls will error out.
ASKER CERTIFIED SOLUTION
Avatar of Pber
Pber
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial