Безопасно ли использовать локальное хранилище потоков для этой операции? - PullRequest
4 голосов
/ 30 ноября 2011

У меня есть веб-приложение ASP.NET, которое позволяет конечным пользователям загружать файлы.Когда файл находится на сервере, я создаю поток для его обработки.В поток передаются данные, касающиеся конкретной операции (UserId, путь к файлу, различные параметры и т. Д.).Большая часть данных передается через объекты и параметры методов, но UserId должна быть доступна более глобально, поэтому я поместил ее в локальное хранилище потоков.

Поток длинный, но он просто обрабатывает файл и прерывает работу.Безопасно ли мое использование названного слота данных в этих обстоятельствах? Если UserA загружает файл, тогда UserB загружает файл, пока первый файл еще обрабатывается, возможно ли, что поток для UserA также будет делегирован для обработки UserB, что приведет к конфликту для именованного слота?т.е. слот перезаписывается идентификатором UserB, а остальная часть файла UserA связана с неверным пользователем, 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

Примечание , которое я не спрашиваюLocalNamedDataStore слоты являются поточно-ориентированными.По определению я знаю, что они есть.

Ответы [ 2 ]

5 голосов
/ 30 ноября 2011

В этом случае использование потокового локального хранилища безопасно. Никакие два потока никогда не будут совместно использовать одно и то же локальное хранилище (следовательно, это поток локальный). Таким образом, нет никаких шансов, что два одновременных запроса будут вытеснены с данными других пользователей.

Пара других комментариев, хотя

  • Избегайте использования Thread.Abort. Это очень опасная операция, и, честно говоря, здесь не нужна Поток завершит оператор позже.
  • Лучшим подходом было бы создать класс, который содержит фоновую операцию с UserId в качестве локального поля. Каждый запрос получает новый экземпляр класса. Это гораздо более простой способ передачи данных в фоновые задачи
2 голосов
/ 30 ноября 2011

Это безопасная операция.

Я должен сказать, что, по мнению JaredPars, было бы лучше создать класс и сохранить идентификатор пользователя в этом классе как поле.по меньшей мере, неполный.

Где вы храните этот объект?Поскольку он создается для каждого запроса, его нужно где-то хранить.Вы связываете страницу с этим функционалом?Я бы не стал.Вы храните в коллекции Context.Items?Это возможно, но что вы делаете с модульными тестами, когда вы пытаетесь абстрагировать код от ASP.Net, чтобы он был более тестируемым?

Я лично сделал гибрид двух подходов:создайте один класс, который будет содержать все элементы данных, которые являются специфическими для запроса, затем я кеширую этот объект в Thread Local Storage.Это позволяет коду запускаться в рамках модульных тестов без необходимости имитации среды выполнения ASP.Net.

Еще один важный момент заключается в следующем: если вы собираетесь использовать асинхронные шаблоны в ASP.Net, вы должны знать, что TLSне пересылать новые потоки при переключении контекста выполнения на новый поток.Это действительно "Thread local".

...