ASP.NET MVC静态变量的安全性如何

Bac*_*tnz 14 asp.net asp.net-mvc thread-safety

我希望确保我的网站能够在将来托管在云上,并且它可以处理大量请求.

静态变量的安全性如何?

它们是不安全的,因为不同用户的单独请求实际上是在共享这些静态变量吗?或者是因为如果您通过线程/分片或类似方式扩展站点,(处理高负载)线程正在共享静态变量?

主要是我有辅助类,具有静态属性,我是否应该更改此体系结构,以便我创建每个类的实例并访问实例?

EG这是我正在做的一个例子:

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 = "no-reply@" + EmailHostName.ToLower();
                        SupportEmailAddress = "support@" + EmailHostName.ToLower();
                        ErrorEmailAddress = "errors@" + 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()
                {

                }
        }
}
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 15

您的代码不是线程安全的.您正在多个请求之间共享静态变量,这些变量可能由多个线程执行.请记住,Dictionary<TKey, TValue>您作为底层存储使用的类不是线程安全类,这意味着如果您尝试OnAppInit从多个线程同时调用该方法,则代码可能会非常严重地崩溃.另一方面,如果您OnAppInit只在Application_Start事件中调用此静态方法一次(保证只从一个线程运行一次),那么在那里使用它是非常安全的.

这就是说静态变量和方法在应用程序中通常是一个坏主意是不正确的.如果您不知道如何正确使用它们,或者如果您需要从并发线程完成此操作,则不知道如何同步对它们的访问,这是一个坏主意.编写线程安全的代码是一个非常困难的主题,如果您担心会出错(在编写ASP.NET应用程序等多线程应用程序时谁不这样做?),就不要像这样共享状态.在ASP.NET应用程序中使用完善的位置:

  • 后端(例如可以是关系数据库)
  • 申请国
  • 高速缓存
  • Http Context State
  • 会话状态
  • 客户端cookie

这些地方专门用于在ASP.NET应用程序中存储状态(当然第一个可以在任何类型的应用程序中使用).

  • 那么这个方法正在修改一个类型为Dictionary的局部静态变量.正如我在答案中所说,这种类型**不是线程安全的**.因此,例如,第一个线程将为字典分配一些值,并在另一个线程将其简单地分配给新字典时,开始向其添加值,从而丢失第一个线程到目前为止可能保存的所有值.永远不应该从多个线程调用此代码. (3认同)