ASP.NET MVC Насколько безопасны статические переменные

Я хочу, чтобы мой сайт мог размещаться в облаке в будущем, а также чтобы он мог обрабатывать множество запросов.

Насколько безопасны статические переменные?

Являются ли они небезопасными, потому что отдельные запросы отдельных пользователей фактически используют эти статические переменные? Или это потому, что если вы распространяете сайт поверх потоков/осколков или подобных, (для обработки больших нагрузок) потоки разделяют статические переменные?

В основном у меня есть классы-помощники со статическими свойствами, следует ли мне изменить эту архитектуру, чтобы вместо этого создать экземпляр каждого класса и получить доступ к экземплярам?

E.G Вот пример того, что я делаю:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Mvc.Mailer;

namespace MVCWebsite.Helpers
{
        public class AppSettings
        {
                public static void OnAppInit()
                {
                        //General
                        AppName = "MyApp";
                        DesktopBaseURLs = new Dictionary<string, string>();
                        DesktopBaseURLs.Add("dev", "localhost:50560");
                        DesktopBaseURLs.Add("test", "www.test.whatever.com");
                        DesktopBaseURLs.Add("live", "www.whatever.com");
                        MobileBaseURLs = new Dictionary<string, string>();
                        MobileBaseURLs.Add("dev", "m.local.whatever.com");
                        MobileBaseURLs.Add("test", "m.test.whatever.com");
                        MobileBaseURLs.Add("live", "m.whatever.com");

                        //Emails
                        EmailHostName = AppName + ".com"; //For the moment atleast
                        NoReplyEmailAddress = "[email protected]" + EmailHostName.ToLower();
                        SupportEmailAddress = "[email protected]" + EmailHostName.ToLower();
                        ErrorEmailAddress = "[email protected]" + EmailHostName.ToLower();

                        //Resources
                        TempFileURL = "/content/temp/";
                        UserDataURL = "/content/user-content/";
                        ProfilePicturesURL = UserDataURL + "profile-pictures/";

                        var a = GlobalHelper.GetURLAsServerPath(ProfilePicturesURL);
                        var b = a;

                }

                //General
                public static string AppName { get; set; }
                public static Dictionary<string, string> DesktopBaseURLs;
                public static Dictionary<string, string> MobileBaseURLs;

                //Emails
                public static string EmailHostName { get; set; }
                public static string NoReplyEmailAddress { get; set; }
                public static string SupportEmailAddress { get; set; }
                public static string ErrorEmailAddress { get; set; }

                //Resources
                public static string UserDataURL { get; set; }
                public static string TempFileURL { get; set; }
                public static string ProfilePicturesURL { get; set; }

                //Methods
                public static void SetAppURL()
                {

                }
        }
}

Ответ 1

Ваш код не является потокобезопасным. Вы используете статические переменные между несколькими запросами, которые потенциально могут выполняться несколькими потоками. Имейте в виду, что класс Dictionary<TKey, TValue>, который вы используете в качестве основного хранилища, не является потокобезопасным классом, означающим, что ваш код может сильно сильно пострадать, если вы попытаетесь вызвать метод OnAppInit одновременно из нескольких потоков. Если, с другой стороны, вы вызываете этот статический метод OnAppInit только один раз внутри вашего события Application_Start (который, как гарантируется, будет выполняться только один раз из одного потока), вы вполне можете его использовать.

Говорят, что статические переменные и методы, как правило, являются плохими идеями в приложениях, это неверно. Это плохая идея, если вы не знаете, как правильно их использовать, или если вы не знаете, как синхронизировать доступ к ним, если вам нужно, чтобы это выполнялось из параллельных потоков. Написание потокобезопасного кода - очень сложный вопрос, и если у вас есть опасения ошибиться (кто не пишет многопоточные приложения, такие как приложение ASP.NET?) Просто не разделяет это состояние. Используйте хорошо установленные места для этого в приложении ASP.NET:

  • Backend (может быть, например, реляционная база данных)
  • Состояние приложения
  • Кэш
  • Контекстное состояние Http
  • Состояние сеанса
  • Файлы cookie клиента

Эти места специально предназначены для хранения состояния в приложении ASP.NET(кроме первого, конечно, который может быть использован в любом типе приложения).

Ответ 2

Статические переменные будут разделяться между запросами. Более того, они будут инициализированы при запуске приложения, поэтому, если AppDomain, таким образом, приложение будет перезапущено, их значения будут повторно инициализированы.