CodeBase-for-DBF icon indicating copy to clipboard operation
CodeBase-for-DBF copied to clipboard

Call Codebase from .net

Open fran-gb opened this issue 6 years ago • 16 comments

I am looking for examples where CodeBase is called from VB.NET or the vb6 file codebase.bas adapted for VB.NET. It exists?

I have doubts of how convert the types of parameter "as any" from vb6 to vb.net.

If someone have samples calling CODEBASE from c# its also wellcome.

fran-gb avatar Sep 24 '19 08:09 fran-gb

Today is your lucky day. Checkout this PR: https://github.com/MPSystemsServices/CodeBase-for-DBF/pull/1

stephen144 avatar Sep 26 '19 16:09 stephen144

Today is your lucky day. Checkout this PR: #1

Thank you, but this info is specific for vb6.

But I've solved it. The parameter defined in VB6 as "as any" and not exists in VB.net can be modified in most cases "as byte()" or "as integer". Until now, I've not found any problem i a few samples that I've tried.

fran-gb avatar Sep 26 '19 17:09 fran-gb

If you need any further examples or assistance, I develop primarily in VB.NET using Codebase.

trevster344 avatar Sep 26 '19 17:09 trevster344

@trevster344 @stephen144 have either of you had any issues with memory leaks when accessing large tables from a .NET Application? When we get the data from a DBF it will assign RAM to the application and never let go, in most cases we end up with GB's of unmanaged memory and my only thought is that the codebase library is holding onto the RAM?

Any guesses?

RicardoJarree avatar Jun 23 '20 14:06 RicardoJarree

@RicardoJarree Are you using read/write optimizations? The only time I have ever had memory leaks with CodeBase was when I wasn't properly disposing of my CodeBase instances in .NET via Dispose() and Finalizer(). I wrote a class that implements IDisposable and just inherit from it when I need to access CodeBase in a class. I have a few classes I wrote that do most of my CodeBase work so I don't have any more memory leaks. All of the classes that implement my disposal class use the Using Statement.

trevster344 avatar Jun 23 '20 14:06 trevster344

@trevster344 thanks for coming back to me. At the moment we access the Data4 datafile object directly. We have a method to controls opening a connection to codebase using the Code4 class and closing either datafiles or the entire codebase connection, and we ensure that we use that. We don't have a class that inherits IDisposable, would you be able to share an example?

RicardoJarree avatar Jun 23 '20 14:06 RicardoJarree

@RicardoJarree Here is a simple example.

` Public MustInherit Class CodebaseDisposal Implements IDisposable

    ''' <summary>
    ''' Flag
    ''' </summary>
    Private Init As Boolean = False

    ''' <summary>
    ''' Flag
    ''' </summary>
    Private _Shutdown As Boolean = False

    ''' <summary>
    ''' Primary codebase instance
    ''' </summary>
    Private _PrimaryCB As Long = 0

    ''' <summary>
    ''' Primary codebase instance for this container
    ''' </summary>
    ''' <returns></returns>
    Public Property PrimaryCB As Long
        Get
            If Not Init Then
                ' Only create an instance once
                Databases.ActivateCodebase(_PrimaryCB) ' Calls code4init
                Init = True
            End If
            Return _PrimaryCB
        End Get
        Set(value As Long)
            _PrimaryCB = value
            Init = True
        End Set
    End Property

#Region "IDisposable Support"
    Private disposedValue As Boolean

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If disposedValue Then Exit Sub
        If disposing Then
            ' TODO: dispose managed state (managed objects).
            GC.SuppressFinalize(Me)
        End If

        ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
        If Me._PrimaryCB > 0 AndAlso Not _Shutdown Then
            DeactivateCodebase(_PrimaryCB) ' Calls code4initundo
            _Shutdown = True
        End If

        disposedValue = True
    End Sub

    Protected Overrides Sub Finalize()
        Try
            Dispose(False)
        Finally
            MyBase.Finalize()
        End Try
    End Sub

    Public Overridable Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
    End Sub
#End Region

End Class`

A large part of this is auto-generated when you implement IDisposable but what is worth noting is the position of the clean-up operations and the usage of Finalizer(). Finalizer is what actually allows the clean-up of unmanaged resources like CodeBase, without it the Garbage Collector will not call Dispose() so if you don't use the Using Statement the garbage collector will be able to take care of your unmanaged resource(CodeBase).

This only matters if you are calling code4init more than once. If you are not then double check read/write optimization code4optimize.

trevster344 avatar Jun 23 '20 14:06 trevster344

@trevster344 thanks for that, I think the main difference which is probably causing the issue is that we are persisting codebase without disposal, whereas you are creating it each time you need it. Thanks again for the advice!

RicardoJarree avatar Jun 23 '20 14:06 RicardoJarree

@RicardoJarree If this is a persistent application like a desktop app and the databases are local I would recommend running an instance of CodeBase only as long as you need but it should be otherwise okay to have a long running instance.

The documentation does state to use u4Free for some cases: This function frees memory previously allocated by other CodeBase functions such as d4fieldInfo. memPtr should point to memory allocated with one of these functions.

Pretty much everything else will be cleaned up by a simple code4initUndo. If nothing here makes sense I would recommend running a memory profiler to make sure it isn't something managed that is leaking. My solutions are mostly for ASP.NET applications because every request is a separate session.

Strings are a pretty common gotcha. Anything string over 85k in memory(large object) gets thrown into the higher heaps which are not GC'd as often as you would want.

trevster344 avatar Jun 23 '20 15:06 trevster344

@trevster344 this is basically an internal WCF webservice and then we have a task which will request and send data to and from the service on a regular basis. It's always running so the RAM creeping up is a major issue.

Had a look in our Codebase.cs file and found u4freeDefault and this is part of the Error4 class but not public. Not sure if you are using the same class to interop with the c4dll library. Nothing stopping me from adding an interop to that method I suppose though.

Running code4initUndo doesn't do anything to help the RAM usage, I've run multiple memory profilers and they all say that the leak is within unmanaged memory. Only around 200kb managed and the rest is unmanaged, anywhere up to 4gb until it crashes due to limits.

My only other thought was the fact that we take what we get from codebase and convert it into a dynamic, but I'm pretty sure even dynamic objects are managed and therefore GC'ed when no longer needed.

RicardoJarree avatar Jun 23 '20 16:06 RicardoJarree

@RicardoJarree Are you using c465net.dll? I am using c4dll.dll but there are compiler switches in my Codebase.vb file for c465net.dll that link u4freeDefault so its more than likely the same method with a different name.

Would you say It's not possible that the code4init code is being run more than once? This sounds a lot like somehow one instance was created, and then another was created and the reference was lost to the first one. This would leave an orphaned CodeBase instance that would be a memory leak and unless you called code4init on the first prior to the second it wouldn't ever be cleaned up.

Your dynamic objects would be managed memory so a memory profiler wouldn't tell you it's unmanaged.

trevster344 avatar Jun 23 '20 16:06 trevster344

Hi Richard,

I’ve read all the e-mail traffic in this thread.

Although I haven’t used codebase++ from .NET, if you are getting a memory leak, try initializing the codebase library, open the tables, and then close the tables and reset the library. See if you get a leak just doing that simple sequence. Also, is it possible you are seeing a memory allocation accrual that is from a lack of garbage collection in .NET? You might try a garbage collection if that is accessible to you.

Hope this helps,

Matt Schifter

From: Richard Jarrett [email protected] Sent: Tuesday, June 23, 2020 10:10 AM To: MPSystemsServices/CodeBase-for-DBF [email protected] Cc: Subscribed [email protected] Subject: Re: [MPSystemsServices/CodeBase-for-DBF] Call Codebase from .net (#5)

@trevster344 https://github.com/trevster344 @stephen144 https://github.com/stephen144 have either of you had any issues with memory leaks when accessing large tables from a .NET Application? When we get the data from a DBF it will assign RAM to the application and never let go, in most cases we end up with GB's of unmanaged memory and my only thought is that the codebase library is holding onto the RAM?

Any guesses?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, https://github.com/MPSystemsServices/CodeBase-for-DBF/issues/5#issuecomment-648175194 view it on GitHub, or https://github.com/notifications/unsubscribe-auth/AJOKIJFM3V5FMHZ4OTFJVTDRYCZUNANCNFSM4IZ4UN6Q unsubscribe.

mschifter avatar Jun 24 '20 13:06 mschifter

@trevster344 I'm using c4dll, I'm wondering if our Codebase.cs file might actually be doing funky bits with starting new instances. We abstract out the calls to a more simple interface, but this class tries to setup it's own instance as well, so if when we call a table the core Codebase.cs file is creating a new codebase instance then it will never get cleared.

I think I will take @mschifter idea and create a very simple console application which makes use of the Codebase.cs file and just opens one of the large tables and then tries to close it again. If that unallocates the memory then the issue is with what we are doing, if not then perhaps there is something wrong with our Codebase.cs file.

If it's not obvious yet, I've adopted this project 😉

RicardoJarree avatar Jun 25 '20 07:06 RicardoJarree

@RicardoJarree If you would like to post the abstract code we can always do a little code review to help you out.

trevster344 avatar Jun 25 '20 15:06 trevster344

Hi Richard,

Just a minor additional idea: if your canonical program does not reproduce the leak, add in the additional calls made to the library one by one or in groups, as is convenient, and look for the leak as you go.

Respectfully,

Matt Schifter

From: Richard Jarrett [email protected] Sent: Thursday, June 25, 2020 3:47 AM To: MPSystemsServices/CodeBase-for-DBF [email protected] Cc: Matt Schifter [email protected]; Mention [email protected] Subject: Re: [MPSystemsServices/CodeBase-for-DBF] Call Codebase from .net (#5)

@trevster344 https://github.com/trevster344 I'm using c4dll, I'm wondering if our Codebase.cs file might actually be doing funky bits with starting new instances. We abstract out the calls to a more simple interface, but this class tries to setup it's own instance as well, so if when we call a table the core Codebase.cs file is creating a new codebase instance then it will never get cleared.

I think I will take @mschifter https://github.com/mschifter idea and create a very simple console application which makes use of the Codebase.cs file and just opens one of the large tables and then tries to close it again. If that unallocates the memory then the issue is with what we are doing, if not then perhaps there is something wrong with our Codebase.cs file.

If it's not obvious yet, I've adopted this project 😉

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MPSystemsServices/CodeBase-for-DBF/issues/5#issuecomment-649326017 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AJOKIJG7QFXY3U6E5DYU54DRYL6I3ANCNFSM4IZ4UN6Q .

mschifter avatar Jun 25 '20 16:06 mschifter

PR #10 has the official C# / VB.NET samples. Although limited and requires some fiddling, they are quite helpful.

phillipsawyer avatar Feb 27 '23 03:02 phillipsawyer