Here's my code:
<ThreadStatic()>
Dim _GlobalConnection As TdConnection
Public Property GlobalConnection As TdConnection
Get
If _GlobalConnection Is Nothing Then
_GlobalConnection = New TdConnection
End If
If _GlobalConnection.State <> ConnectionState.Open Then
OpenConnection(_GlobalConnection)
End If
Return _GlobalConnection
End Get
Set(ByVal value As TdConnection)
_GlobalConnection = value
End Set
End Property
It's in a module within an ASP.NET web app, so all members are shared/static by definition. My goal here is essentially laziness. I use connections everywhere, so it just made sense to have one property that is thread static so that it serves as a new instance per thread instead of dimming a new connection object every time I want to use it.
This seems to have been working until I decided to load the same page in two separate browsers. When I do this, an exception is thrown that states the connection object is already in use.
I read in a Microsoft article that instance types are not guaranteed to be thread safe. If this is the case, what can I do to ensure that this property and its field are thread safe?
Edit: What has be confused is that this code works within the page load event:
Dim Tasks As New List(Of Task)
Tasks.Add(Task.Factory.StartNew(Sub() ucEmployee.LoadData()))
Tasks.Add(Task.Factory.StartNew(Sub() ucSales.LoadData()))
Tasks.Add(Task.Factory.StartNew(Sub() ucServers.LoadData()))
Tasks.Add(Task.Factory.StartNew(Sub() ucApps.LoadData()))
Task.WaitAll(Tasks.ToArray())
Each one of those .LoadData() methods is executed in a separate thread and all of them reference my GlobalConnection property above. I initially wrote all that without the ThreadStatic attribute. After encountering errors, I made the GlobalConnection property ThreadStatic and the problem went away. When this rolls out into production, this web app will be used by multiple people. This is what prompted me to open the same page in two web browsers. I thought that would have been two separate threads right there, but perhaps I am wrong about that.
You should have one connection per request instead of one per thread.
To do that, store it in HttpContext.Current.Items
instead of the ThreadStatic field.
You should also close the connection in an EndRequest
handler.