李维强-15级 发表于 2016-12-5 03:14:21

C# 多线程下HttpContext.Current

本帖最后由 李维强-15级 于 2016-12-5 03:47 编辑

又是多线程,以前那次C++把我卡得差点不能给客户交货,这次这个卡了我两天。。。。现在我用取巧的办法解决了,但是任然不明其理。
事情是这样的,微信公众号里面需要全局缓存令牌盾,但是令牌盾是有过期时间的,而且每天有申请令牌盾的次数限制,所以我开个线程来做这个事情,然后在线程里面访问事先申请好了的全局变量,这样就可以弄了。但是在MVC架构里面申请全局变量是用的Application.Add("变量名", 0);这样来申请的(话说我只会这一种),然后在其他地方使用HttpContext.Current.Application["变量名"]这样来调用,进行读取和修改。
好了,我这里使用以下代码来做的
首先在Global.asax里面的Application_Start()里面定义一个变量,同样在这个函数里面开启线程。

      
    protected void Application_Start()
      {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            Application.Add("gtest", 0);
            
            acc_TokenClass mythread = new acc_TokenClass();
            mythread.start();
      }




然后在线程里面使用这个变量HttpContext.Current.Application["gtest"];
下面是线程的函数


namespace HTMLTest.myThread
{
    public class acc_TokenClass
    {
      BaseDao basedao = new BaseDao();
      Thread thread = null;
      public bool isOpen = false
      public void run()
      {
            while (true)
            {
                if (thread != null)
                {
                  HttpContext.Current.Application["gtest"] = 5;
                }
                Thread.Sleep(60000 * 90);
            }
      }
      public void start()
      {
            if (thread == null)
            {
                thread = new Thread(run);
                isOpen = true;
                thread.Start();
            }
      }
    }
}


然后问题来了,在线程里面使用的时候发现HttpContext.Current直接是NULL,然后我百度,看到好多人都遇到这个问题,回头想想,这个也很正常,线程是独立资源嘛,不可能有主线程的东西的。下面就是如何解决,我看了网上的朋友,很多就是开委托,或者访问HttpRuntime,等情况。苦与我任务缠身,一直都没有去学C#,导致网上说的那些方法我都不会。

最后我采用了一种取巧的方法。
首先我在acc_TokenClass这个类里面定义一个变量public HttpContext context;然后在Application_Start()里面给这个变量赋值mythread.context = HttpContext.Current;这样就把当前的HttpContext.Current传到线程的那个类里面去了,然后在线程里面调用就一切正常了。
代码如下
      
       protected void Application_Start()
      {
                .....
            
            acc_TokenClass mythread = new acc_TokenClass();
            mythread.context = HttpContext.Current;                //这里把当前的current赋值过去
            mythread.start();
      }


   
namespace HTMLTest.myThread
{
    public class acc_TokenClass
    {
      BaseDao basedao = new BaseDao();
      Thread thread = null;
      public bool isOpen = false
      public HttpContext context;   //这里在类里面定义一个变量
      public void run()
      {
            while (true)
            {
                if (thread != null)
                {
                  context.Application["gtest"] = 5;       //这里直接调用赋值即可,我试了试可行的
                }
                Thread.Sleep(60000 * 90);
            }
      }
      public void start()
      {
            if (thread == null)
            {
                thread = new Thread(run);
                isOpen = true;
                thread.Start();
            }
      }
    }
}


最后我想问下各位,虽然我能够调用全局变量了,但是我这种方法会不会不对?会不会产生副作用?什么内存泄露什么的?


李维强-15级 发表于 2016-12-5 03:17:14

以下是网上相关帖子的解决方法,大多是使用异步的调用,建立委托来做
http://blog.csdn.net/neusoft06/article/details/41960039

这个是分析httpcontext.current的
http://www.cnblogs.com/scy251147/p/3549503.html

HttpContext.Current并非无处不在
http://www.cnblogs.com/fish-li/archive/2013/04/06/3002940.html

最后一个讲原理的
我心目中的Asp.net核心对象
http://www.cnblogs.com/fish-li/archive/2011/08/21/2148640.html

顾福源 发表于 2016-12-5 22:41:31

同一个进程里面的全局变量在线程里面还无法引用?:o

李维强-15级 发表于 2016-12-7 09:39:46

顾福源 发表于 2016-12-5 22:41
同一个进程里面的全局变量在线程里面还无法引用?

网站这个C#里面MVC机制是分了的,可以调用,但是事先要注入,有点麻烦。
页: [1]
查看完整版本: C# 多线程下HttpContext.Current