[SOLVED] Is using thread local storage safe for this operation?

Issue

I have a ASP.NET web application that allows end users to upload a file. Once the file is on the server, I spawn a thread to process the file. The thread is passed data regarding the specific operation (UserId, file path, various options, etc.). Most of the data is passed around via objects and method parameters but UserId needs to be available more globally so I put it in thread-local storage.

The thread is lengthy but it just processes the file and aborts. Is my use of the named data slot safe in this circumstance? If UserA uploads a file then UserB uploads a file while the first file is still processing, is it possible that the thread for UserA will also be delegated to handle UserB, thus producing a conflict for the named slot? (i.e. The slot gets overwritten with UserB’s id and the rest of the operation of UserA’s file is linked to the wrong User, UserB).

Public Class FileUploadProcess
    Public UserId as String

    Public Sub ExecuteAsync()
        Dim t As New Thread(New ThreadStart(AddressOf ProcessFile))
        t.Start()
    End Sub

    Protected Sub ProcessFile()
        Dim slot As LocalDataStoreSlot = Thread.GetNamedDataSlot("UserId")
        Thread.SetData(slot, UserId)

        'lengthy operation to process file

        Thread.FreeNamedDataSlot("UserId")
        Thread.CurrentThread.Abort()
    End Sub
End Class

Note that I am not asking if the LocalNamedDataStore slots are thread-safe. By definition, I know that they are.

Solution

In this case your use of thread local storage is safe. No two threads will ever share the same local storage (hence it’s thread local). So there is no chance that two concurrent requests will stomp on the others data.

Couple of other comments though

  • Do avoid the use of Thread.Abort. It’s a very dangerous operation and truthfully not needed here. The thread will end the statement afterwards.
  • A better approach would be to create a class which contains the background operation that has the UserId as a local field. Each request gets a new class instance. This is a much easier way to pass the data around to the background tasks

Answered By – JaredPar

Answer Checked By – Timothy Miller (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *