Hi,
I have figured out that .NET CLR implements object destruction on the
knowledge of usage of
these objects. My DBHelper class closes the connection when refcount
goes to zero. That happens inside Finalize.
The sample code at the end crashes when I not do a call to getReader
with an empty string.
That is used as a Dummy for ' This object is used until here '
information.
If I use the last getReader line, All is fine.
I came from C++ and expected that GC doesn't touch objects in the same
scope (stack).
This makes me struggling on how to close connections automatically in
Finalize whithout
explicitly set the object to NULL. (In C++ I have smart pointers that
do this for me)
Any Ideas ?
Thanks, Lothar
Public Class DBHelper
Shared conn As SqlClient.SqlCo nnection
Shared refcount As Integer
Public Sub New(ByVal where As String)
refcount = refcount + 1
End Sub
Public Function getReader(ByVal SQL As String) As
SqlClient.SqlDa taReader
Dim mycmd As SqlClient.SqlCo mmand
Dim reader As SqlClient.SqlDa taReader = Nothing
' Return on empty query
If SQL = "" Then
Return Nothing
End If
Try
If conn Is Nothing Then
conn = New
SqlClient.SqlCo nnection("conne ctionstring")
End If
conn.Open()
Catch ex As Exception
' Log some information
conn = Nothing
Return Nothing
End Try
mycmd = conn.CreateComm and
mycmd.CommandTe xt = SQL
Try
reader = mycmd.ExecuteRe ader()
'CommandBehavio r.CloseConnecti on)
Catch ex As Exception
' Log some information
reader = Nothing
Return Nothing
End Try
Return reader
End Function
Protected Overrides Sub Finalize()
If refcount 0 Then
refcount = refcount - 1
If refcount = 0 Then
Try
conn.Close()
conn = Nothing
Catch ex As Exception
End Try
End If
End If
MyBase.Finalize ()
End Sub
Sample:
Public Sub SomeFunction()
Dim dbHelper As DBHelper = New DBHelper()
Dim reader As SqlClient.SqlDa taReader
Dim SQL As String = "SELECT * from SomeTable"
reader = dbHelper.getRea der(SQL)
GC.Collect() ' A
Collect to be appear explicitly or indirectly in
' my code
System.Threadin g.Thread.Sleep( 10) ' Some time
consumption
If Not reader Is Nothing Then
While
reader.Read() ' Crash
Dim SomeField As String = reader.GetValue (0)
End While
End If
'dbHelper.Execu teScalar("") ' Doesn't crash when
this line is uncommented.
End Sub 7 1560
Implement the IDisposable pattern, disposing the connection in "Dispose",
not Finalize.
Public MyClass
Implements IDisposable
...
End Class
<lo************ @lollisoft.dewr ote in message
news:11******** *************@q 75g2000hsh.goog legroups.com...
Hi,
I have figured out that .NET CLR implements object destruction on the
knowledge of usage of
these objects. My DBHelper class closes the connection when refcount
goes to zero. That happens inside Finalize.
The sample code at the end crashes when I not do a call to getReader
with an empty string.
That is used as a Dummy for ' This object is used until here '
information.
If I use the last getReader line, All is fine.
I came from C++ and expected that GC doesn't touch objects in the same
scope (stack).
This makes me struggling on how to close connections automatically in
Finalize whithout
explicitly set the object to NULL. (In C++ I have smart pointers that
do this for me)
Any Ideas ?
Thanks, Lothar
Public Class DBHelper
Shared conn As SqlClient.SqlCo nnection
Shared refcount As Integer
Public Sub New(ByVal where As String)
refcount = refcount + 1
End Sub
Public Function getReader(ByVal SQL As String) As
SqlClient.SqlDa taReader
Dim mycmd As SqlClient.SqlCo mmand
Dim reader As SqlClient.SqlDa taReader = Nothing
' Return on empty query
If SQL = "" Then
Return Nothing
End If
Try
If conn Is Nothing Then
conn = New
SqlClient.SqlCo nnection("conne ctionstring")
End If
conn.Open()
Catch ex As Exception
' Log some information
conn = Nothing
Return Nothing
End Try
mycmd = conn.CreateComm and
mycmd.CommandTe xt = SQL
Try
reader = mycmd.ExecuteRe ader()
'CommandBehavio r.CloseConnecti on)
Catch ex As Exception
' Log some information
reader = Nothing
Return Nothing
End Try
Return reader
End Function
Protected Overrides Sub Finalize()
If refcount 0 Then
refcount = refcount - 1
If refcount = 0 Then
Try
conn.Close()
conn = Nothing
Catch ex As Exception
End Try
End If
End If
MyBase.Finalize ()
End Sub
Sample:
Public Sub SomeFunction()
Dim dbHelper As DBHelper = New DBHelper()
Dim reader As SqlClient.SqlDa taReader
Dim SQL As String = "SELECT * from SomeTable"
reader = dbHelper.getRea der(SQL)
GC.Collect() ' A
Collect to be appear explicitly or indirectly in
' my code
System.Threadin g.Thread.Sleep( 10) ' Some time
consumption
If Not reader Is Nothing Then
While
reader.Read() ' Crash
Dim SomeField As String = reader.GetValue (0)
End While
End If
'dbHelper.Execu teScalar("") ' Doesn't crash when
this line is uncommented.
End Sub
On 19 Apr., 11:52, "Duracel" <Dura...@nospam .comwrote:
Implement the IDisposable pattern, disposing the connection in "Dispose",
not Finalize.
Public MyClass
Implements IDisposable
...
End Class
<lothar.behr... @lollisoft.dewr ote in message
news:11******** *************@q 75g2000hsh.goog legroups.com...
Hi,
I have figured out that .NET CLR implements object destruction on the
knowledge of usage of
these objects. My DBHelper class closes the connection when refcount
goes to zero. That happens inside Finalize.
The sample code at the end crashes when I not do a call to getReader
with an empty string.
That is used as a Dummy for ' This object is used until here '
information.
If I use the last getReader line, All is fine.
I came from C++ and expected that GC doesn't touch objects in the same
scope (stack).
This makes me struggling on how to close connections automatically in
Finalize whithout
explicitly set the object to NULL. (In C++ I have smart pointers that
do this for me)
Any Ideas ?
Thanks, Lothar
Public Class DBHelper
Shared conn As SqlClient.SqlCo nnection
Shared refcount As Integer
Public Sub New(ByVal where As String)
refcount = refcount + 1
End Sub
Public Function getReader(ByVal SQL As String) As
SqlClient.SqlDa taReader
Dim mycmd As SqlClient.SqlCo mmand
Dim reader As SqlClient.SqlDa taReader = Nothing
' Return on empty query
If SQL = "" Then
Return Nothing
End If
Try
If conn Is Nothing Then
conn = New
SqlClient.SqlCo nnection("conne ctionstring")
End If
conn.Open()
Catch ex As Exception
' Log some information
conn = Nothing
Return Nothing
End Try
mycmd = conn.CreateComm and
mycmd.CommandTe xt = SQL
Try
reader = mycmd.ExecuteRe ader()
'CommandBehavio r.CloseConnecti on)
Catch ex As Exception
' Log some information
reader = Nothing
Return Nothing
End Try
Return reader
End Function
Protected Overrides Sub Finalize()
If refcount 0 Then
refcount = refcount - 1
If refcount = 0 Then
Try
conn.Close()
conn = Nothing
Catch ex As Exception
End Try
End If
End If
MyBase.Finalize ()
End Sub
Sample:
Public Sub SomeFunction()
Dim dbHelper As DBHelper = New DBHelper()
Dim reader As SqlClient.SqlDa taReader
Dim SQL As String = "SELECT * from SomeTable"
reader = dbHelper.getRea der(SQL)
GC.Collect() ' A
Collect to be appear explicitly or indirectly in
' my code
System.Threadin g.Thread.Sleep( 10) ' Some time
consumption
If Not reader Is Nothing Then
While
reader.Read() ' Crash
Dim SomeField As String = reader.GetValue (0)
End While
End If
'dbHelper.Execu teScalar("") ' Doesn't crash when
this line is uncommented.
End Sub- Zitierten Text ausblenden -
- Zitierten Text anzeigen -
As of the documentation it does the same as Finalize. I cannot
guarantee, that the reader is usable after getReader(...).
It is the time, when GC calls Finalize or now Dispose through
Finalize. It appears BEFORE my function block is leaving.
I have to go through my whole project and add this dummy call to avoid
too early object destructions.
That's bad.
imho, where you are using resources that implement IDisposable, you should
dispose of them yourself, rather than waiting for the GC to kick in. From a
C++ background, you are used to deterministic object destruction - whereas
you never really know with .NET when the object will be disposed so in cases
where its important to manage resources, you should make sure it happens
when you want it to:
Using g as Graphics = myControl.Creat eGraphics ()
End Using
' g has automagically been disposed, even if an exception occurs
or
Dim g as Graphics = Nothing
Try
g = myControl.Creat eGraphics ()
Finally
' g gets disposed, even if an exception occurs
If g IsNot Nothing Then
g.Dispose ()
End If
End Try
On 19 Apr., 12:21, "Duracel" <Dura...@nospam .comwrote:
imho, where you are using resources that implement IDisposable, you should
dispose of them yourself, rather than waiting for the GC to kick in. From a
C++ background, you are used to deterministic object destruction - whereas
you never really know with .NET when the object will be disposed so in cases
where its important to manage resources, you should make sure it happens
when you want it to:
Using g as Graphics = myControl.Creat eGraphics ()
End Using
' g has automagically been disposed, even if an exception occurs
or
Dim g as Graphics = Nothing
Try
g = myControl.Creat eGraphics ()
Finally
' g gets disposed, even if an exception occurs
If g IsNot Nothing Then
g.Dispose ()
End If
End Try
Is it possible to force a class to be only used by Using ?
I mean, to help avoid making mistakes in the future.
A quick hack would be a regex replace of Dim [A-Z*][a-z*] As DBHelper
with Using dbhelper as DBHelper over the whole project.
Right ?
Is it possible to force a class to be only used by Using ?
I mean, to help avoid making mistakes in the future.
A quick hack would be a regex replace of Dim [A-Z*][a-z*] As DBHelper
with Using dbhelper as DBHelper over the whole project.
Right ?
Well if you implement IDisposable, you know your connection will dissapear
when the GC collects it, you just don't know when. I would be loathe to
search/replace something like this - rather Find In Files, all instances of
New DBHelper and take it from there. Either use "Using" or use Try/Finally
combination. Take a look at the "Using" keyword either online or in MSDN to
get more information about it before you decided on replacing all instances
of DBHelper in code.
Hope this helps.
On Apr 19, 4:41 am, "lothar.behr... @lollisoft.de"
<lothar.behr... @lollisoft.dewr ote:
Hi,
I have figured out that .NET CLR implements object destruction on the
knowledge of usage of
these objects. My DBHelper class closes the connection when refcount
goes to zero. That happens inside Finalize.
The sample code at the end crashes when I not do a call to getReader
with an empty string.
That is used as a Dummy for ' This object is used until here '
information.
If I use the last getReader line, All is fine.
I came from C++ and expected that GC doesn't touch objects in the same
scope (stack).
This makes me struggling on how to close connections automatically in
Finalize whithout
explicitly set the object to NULL. (In C++ I have smart pointers that
do this for me)
Any Ideas ?
Thanks, Lothar
Public Class DBHelper
Shared conn As SqlClient.SqlCo nnection
Shared refcount As Integer
Public Sub New(ByVal where As String)
refcount = refcount + 1
End Sub
Public Function getReader(ByVal SQL As String) As
SqlClient.SqlDa taReader
Dim mycmd As SqlClient.SqlCo mmand
Dim reader As SqlClient.SqlDa taReader = Nothing
' Return on empty query
If SQL = "" Then
Return Nothing
End If
Try
If conn Is Nothing Then
conn = New
SqlClient.SqlCo nnection("conne ctionstring")
End If
conn.Open()
Catch ex As Exception
' Log some information
conn = Nothing
Return Nothing
End Try
mycmd = conn.CreateComm and
mycmd.CommandTe xt = SQL
Try
reader = mycmd.ExecuteRe ader()
'CommandBehavio r.CloseConnecti on)
Catch ex As Exception
' Log some information
reader = Nothing
Return Nothing
End Try
Return reader
End Function
Protected Overrides Sub Finalize()
If refcount 0 Then
refcount = refcount - 1
If refcount = 0 Then
Try
conn.Close()
conn = Nothing
Catch ex As Exception
End Try
End If
End If
MyBase.Finalize ()
End Sub
Sample:
Public Sub SomeFunction()
Dim dbHelper As DBHelper = New DBHelper()
Dim reader As SqlClient.SqlDa taReader
Dim SQL As String = "SELECT * from SomeTable"
reader = dbHelper.getRea der(SQL)
GC.Collect() ' A
Collect to be appear explicitly or indirectly in
' my code
System.Threadin g.Thread.Sleep( 10) ' Some time
consumption
If Not reader Is Nothing Then
While
reader.Read() ' Crash
Dim SomeField As String = reader.GetValue (0)
End While
End If
'dbHelper.Execu teScalar("") ' Doesn't crash when
this line is uncommented.
End Sub
First, it looks like you're using DBHelper as a mechanism for keeping
a connection open. ADO.NET already supports connection pooling so
DBHelper isn't really buying you anything.
Second, assuming you want to continue using DBHelper, you should be
implementing IDisposable since it is logically holds unmanaged
resources. I don't actually see a problem with the Finalize method
per se, but I get the feeling that it is okay by accident. There are
certain things you cannot do from Finalize. Read the following on
implementing IDisposable correctly. http://msdn2.microsoft.com/en-us/library/fs2xkftw.aspx
Third, the Finalize is partly responsible for the crash. You said
that by uncommenting the dbHelper.Execut eScalar line the crash no
longer occurs. This is very confusing, but let me try to explain.
The Finalize method is executed when the object is collected the GC.
The GC is *very* aggressive. It can see that dbHelper is no longer
used after the call to getReader. At that point it becomes eligible
for collection immediately. That in turn causes Finalize to run which
closes the SqlConnection and invalidates the SqlDbReader. By
uncommenting the dbHelper.Execut eScalar call the GC sees that it is
used later and so it is not yet available for collection.
lothar.behrens wrote:
<backposted/>
The problem is that in SomeFunction you make an explicit call to the
GC. The GC sees that DBHelper isn't being used anymore and naturally
collects the object, thus triggering your finalize and hence the
demise of the connection.
In other words, you're doing it wrong... =)))))
Why? Because the connection is still being used -- even after DBHelper
has been shutdown: a DataReader *requires* an open connection to
operate. Because DBHelper didn't provide for that, the connection was
already dead when the reader tried to use it. That's why you crashed.
Add an explicit CloseConnection method to your DBHelper, so users know
that it must be closed *after* the connection was used (that is, after
any DataReaders fade out). Or create a ReaderAdapter of some kind,
shielding the actual DataAdapter, to allow for you to correctly track
the connection's life time (this would require that the adapter kept a
reference to the original DBHelper, so to prevent it from a premature
death).
And ditch that refcount. You have no way of controlling that (yes, you
probably do, but it's too much work).
HTH.
Regards,
Branco.
Hi,
I have figured out that .NET CLR implements object destruction on the
knowledge of usage of
these objects. My DBHelper class closes the connection when refcount
goes to zero. That happens inside Finalize.
The sample code at the end crashes when I not do a call to getReader
with an empty string.
That is used as a Dummy for ' This object is used until here '
information.
If I use the last getReader line, All is fine.
I came from C++ and expected that GC doesn't touch objects in the same
scope (stack).
This makes me struggling on how to close connections automatically in
Finalize whithout
explicitly set the object to NULL. (In C++ I have smart pointers that
do this for me)
Any Ideas ?
Thanks, Lothar
Public Class DBHelper
Shared conn As SqlClient.SqlCo nnection
Shared refcount As Integer
Public Sub New(ByVal where As String)
refcount = refcount + 1
End Sub
Public Function getReader(ByVal SQL As String) As
SqlClient.SqlDa taReader
Dim mycmd As SqlClient.SqlCo mmand
Dim reader As SqlClient.SqlDa taReader = Nothing
' Return on empty query
If SQL = "" Then
Return Nothing
End If
Try
If conn Is Nothing Then
conn = New
SqlClient.SqlCo nnection("conne ctionstring")
End If
conn.Open()
Catch ex As Exception
' Log some information
conn = Nothing
Return Nothing
End Try
mycmd = conn.CreateComm and
mycmd.CommandTe xt = SQL
Try
reader = mycmd.ExecuteRe ader()
'CommandBehavio r.CloseConnecti on)
Catch ex As Exception
' Log some information
reader = Nothing
Return Nothing
End Try
Return reader
End Function
Protected Overrides Sub Finalize()
If refcount 0 Then
refcount = refcount - 1
If refcount = 0 Then
Try
conn.Close()
conn = Nothing
Catch ex As Exception
End Try
End If
End If
MyBase.Finalize ()
End Sub
Sample:
Public Sub SomeFunction()
Dim dbHelper As DBHelper = New DBHelper()
Dim reader As SqlClient.SqlDa taReader
Dim SQL As String = "SELECT * from SomeTable"
reader = dbHelper.getRea der(SQL)
GC.Collect() ' A
Collect to be appear explicitly or indirectly in
' my code
System.Threadin g.Thread.Sleep( 10) ' Some time
consumption
If Not reader Is Nothing Then
While
reader.Read() ' Crash
Dim SomeField As String = reader.GetValue (0)
End While
End If
'dbHelper.Execu teScalar("") ' Doesn't crash when
this line is uncommented.
End Sub
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Frank Passek |
last post by:
Dear all,
I've encountered some strange behaviour with PHP (4.3.2) using the CLI-API.
When I provide an option in the first line of my script like so:
#!/usr/bin/php -c /path_to_my_ini_file
and call the script from the (bash-)commandline, PHP seems to ignore this
setting.
Calling the script with:
php -c /path_to_my_ini_file myscript.php
|
by: Phil |
last post by:
Hi,
I don't understand this strange behaviour:
I compile this code :
#include <Python.h>
#include"Numeric/arrayobject.h"
static PyObject *
|
by: Paul Drummond |
last post by:
Hi all,
I am developing software for Linux Redhat9 and I have noticed some very
strange behaviour when throwing exceptions within a shared library.
All our exceptions are derived from std::exception. We have a base
class which all processes derive from which is always instantiated in
main surrounded by a try/catch(std::exception) which catches all
exceptions that have not be handled at a higher level. The catch block
cleans up and...
|
by: Bruno van Dooren |
last post by:
Hi All,
i have some (3) different weird pointer problems that have me stumped. i
suspect that the compiler behavior is correct because gcc shows the same
results.
----------------------------------------------
//example 1:
typedef int t_Array;
int main(int argc, char* argv)
|
by: Sebastian C. |
last post by:
Hello everybody
Since I upgraded my Office XP Professional to SP3 I got strange
behaviour.
Pieces of code which works for 3 years now are suddenly stop to work
properly.
I have Office XP Developer (SP3 for Office, SP1 for developer,
JET40SP8) on Windows XP Home Edition (SP1). The same behaviour occurs
on Windows 98 too.
| |
by: Edd Dawson |
last post by:
Hi. I have a strange problem involving the passing of command line
arguments to a C program I'm writing. I tried posting this in
comp.programming yesterday but someone kindly suggested that I'd have
better luck here. So here goes!
My program ignores any command line arguments, or at least it's
supposed to. However, when I pass any command line arguments to the
program, the behaviour of one of the functions changes mysteriously. I
have...
|
by: DeltaOne |
last post by:
#include<stdio.h>
typedef struct test{
int i;
int j;
}test;
main(){
test var;
var.i=10;
var.j=20;
|
by: Gotch |
last post by:
Hi,
I'm getting a very strange behaviour while running a project I've
done.... Let's expose it: I've two projects. Both of them use a Form
to do some Gui stuff. Other threads pack up messages this way like:
public class UiMsg
{
public enum MsgType { StatusOk };
public MsgType Type;
|
by: Dox33 |
last post by:
I ran into a very strange behaviour of raw_input().
I hope somebody can tell me how to fix this.
(Or is this a problem in the python source?)
I will explain the problem by using 3 examples. (Sorry, long email)
The first two examples are behaving normal, the thirth is
strange.......
I wrote the following flabbergasting code:
#-------------------------------------------------------------
|
by: Pilcrow |
last post by:
This behavior seems very strange to me, but I imagine that someone will
be able to 'explain' it in terms of the famous C standard.
-------------------- code -----------------------------------
#include <stdio.h>
int main (void)
{
char xx="abcd";
char * p1 = xx;
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
| |
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
| |
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |