重工电子论坛

标题: C# 多线程下HttpContext.Current [打印本页]

作者: 李维强-15级    时间: 2016-12-5 03:14
标题: C# 多线程下HttpContext.Current
本帖最后由 李维强-15级 于 2016-12-5 03:47 编辑

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

[C#] syntaxhighlighter_viewsource syntaxhighlighter_copycode
       
    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"];
下面是线程的函数

[C#] syntaxhighlighter_viewsource syntaxhighlighter_copycode

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传到线程的那个类里面去了,然后在线程里面调用就一切正常了。
代码如下
[C#] syntaxhighlighter_viewsource syntaxhighlighter_copycode
        
       protected void Application_Start()
        {
                .....
            
            acc_TokenClass mythread = new acc_TokenClass();
            mythread.context = HttpContext.Current;                //这里把当前的current赋值过去
            mythread.start();
        }


[C#] syntaxhighlighter_viewsource syntaxhighlighter_copycode
   
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
以下是网上相关帖子的解决方法,大多是使用异步的调用,建立委托来做
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
同一个进程里面的全局变量在线程里面还无法引用?
作者: 李维强-15级    时间: 2016-12-7 09:39
顾福源 发表于 2016-12-5 22:41
同一个进程里面的全局变量在线程里面还无法引用?

网站这个C#里面MVC机制是分了的,可以调用,但是事先要注入,有点麻烦。




欢迎光临 重工电子论坛 (http://cqutlab.cn/) Powered by Discuz! X3.1