4

Is this the right way of declaration dbreaders when mulitple users access the same page?

public dbReader as system.Data.IDataReader at class level or

Dim dbReader as System.Data.IDataReader in each function inside a class.

What would be the best practice to make the dbReader thread safe in VB.Net?

Does declaring them as static makes it thread safe?

Thanks in Advance,

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
sony
  • 51
  • 1
  • 3
  • 6

3 Answers3

3

If you'd like each thread to modify the variable without 'fear' another thread will change it somewhere along the line, it is best you adorn the variable with the ThreadStatic attribute.

The ThreadStatic attribute creates a different instance of the variable for each thread that's created so you're confident there won't be any race conditions.

Example (from MSDN)

Imports System
<ThreadStatic> Shared value As Integer
Alex Essilfie
  • 12,339
  • 9
  • 70
  • 108
1

I would recommend you using reentrant functions when possible which are thread safe by definition instead of using class fields:

Function GetIds() As IEnumerable(Of Integer)
    Dim result = New List(Of Integer)()
    Using conn = New SqlConnection("SomeConnectionString")
        Using cmd = conn.CreateCommand()
            conn.Open()
            cmd.CommandText = "SELECT id FROM foo"
            Using reader = cmd.ExecuteReader()
                While reader.Read()
                    result.Add(reader.GetInt32(0))
                End While
            End Using
        End Using
    End Using
    Return result
End Function
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I use DAAB to open and close connections. And then call that data access method which in turn returns resultset as dbreader.From aspx page I will declare a dbreader , get that data and use it. for example – sony Oct 12 '10 at 16:55
  • If sClose = 1 And iAssnKey > 0 Then dbReader = DAL.GetAssnCtrlPKey(ClientKey, iAssnKey) If Validation.Validate_DataReader(dbReader) Then If dbReader.Read = True Then If DB_Objects.Convert_objToBool(dbReader.Item("Active")) = False Then sClose = 0 End If End If End If Validation.Close_DataReader(dbReader) End If – sony Oct 12 '10 at 16:56
  • You shouldn't be closing connections. You should simply dispose them as in my example so that they are properly returned to the connection pool. No class/static fields needed. – Darin Dimitrov Oct 12 '10 at 16:58
  • so first when I call a data access method it opens the connection returns the data . Once I use the data I should dispose the dbreader.Like dbReader.Dispose(). And I do not close connection anywhere explicity. – sony Oct 12 '10 at 17:01
  • Just use `Using` as in my example. It will take care of everything. You don't need to explicitly call `reader.Dispose`. – Darin Dimitrov Oct 12 '10 at 17:04
  • So I should use using statement in the DAAB data access method in mycase http://social.msdn.microsoft.com/Forums/en/adodotnetdataproviders/thread/25b9bcdc-5aca-4831-a80d-a1f981e2ee64 Darin if you can see this link where I posted an issue, basically I posted the current thread in relation to the one on the link. If can give me an idea if this because of thread safe issue. that would be great. – sony Oct 12 '10 at 17:18
1

If you are Diming the variable in a function, no other thread can access that variable making it thread-safe by definition.

However, if you are declaring it at a class level, you might want to use SyncLock which will prevent other threads from accessing it if it is currently being used by an other one.

Example:

Public Sub AccessVariable()
    SyncLock Me.dbReader
         'Work With dbReader
    End SyncLock
End Sub
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
  • so if another thread is also accessing the same page same reader and trying to update or insert that reader which is coded as Synlock. Would that result in any inconsistencies of data being retrieved . – sony Oct 12 '10 at 17:23
  • @sony: Not if you use `SyncLock` like above everytime to work with the variable. `SyncLock` is made to prevent two threads from working on the same variable. The second thread will sleep until the lock is released. – Andrew Moore Oct 12 '10 at 17:35
  • Ok that helps. and what do you suggest , say I have 3 functions inside a class. Each of these functions call a different dataaccess method and gets the result set as data reader. Now I declare a data reader in the aspx page and say like dbreader=GetFunction1Data(pkey). – sony Oct 12 '10 at 17:59
  • Now inorder to open the reader thread safe mode , I should put it this way. public sub function1() – sony Oct 12 '10 at 18:00
  • synclock Me.dbreader 'work with dbreader end synclock end sub – sony Oct 12 '10 at 18:01
  • At the sametime a second function call a datareader in another thread , it will not interrupt the one already started. – sony Oct 12 '10 at 18:03
  • Is this right that I have to put the synclock in the aspx page? – sony Oct 12 '10 at 18:04
  • And how should the dbreader should be declared at class level or the function level on the aspx page. – sony Oct 12 '10 at 18:05
  • @sony: It doesn't matter if you use different functions. As long as you are `SyncLock` using the same object, you'll be fine. It only interrupts (actually, pauses) the second operation until the first one frees the lock. If you need access at multiple locations, then use class level variable. If you need only function level access, don't use SyncLock and `Dim` in the function. A function can only be executed by one thread at a time (well, if another thread runs the same function, it will be a totally different dbReader variable). – Andrew Moore Oct 12 '10 at 21:41