Is using thread local storage safe for this operation?

六眼飞鱼酱① 提交于 2019-12-07 10:10:44

问题


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.


回答1:


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



回答2:


This is a safe operation.

I have to say that I that JaredPars opinion that it would be better to create a class and store the userid in that class as a field is incomplete to say the least.

Where do you then store that object? Since it is created per request you have to store it somewhere. Do you couple the page with this functionality? I wouldn't. Do you store in the Context.Items collection? That is a possibility but what do you do with unit tests where you are trying to abstract the code away from ASP.Net so it will be more testable?

I have personally done a hybrid of the two approaches: I create a single class that will contain all of the data elements that are request specific then I cache that object in Thread Local Storage. This allows the code to run in unit test frameworks without having to mock the ASP.Net runtime environment.

Another important point is this: if you intend to use asynchronous patterns in ASP.Net you should be aware that TLS is not forward to new threads when switching the execution context to a new thread. It is truly "Thread local".



来源:https://stackoverflow.com/questions/8317203/is-using-thread-local-storage-safe-for-this-operation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!