ASP.NET中的全局变量 [英] Global variable in ASP.NET

查看:76
本文介绍了ASP.NET中的全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望在另一个线程仍在执行该代码位时停止一个线程输入代码:

I wish to stop a thread from entering code while another thread is still executing that bit of code:

我目前正在执行以下操作: global.asax.cs

I'm currently going the following: global.asax.cs

    private static bool _isProcessingNewIllustrationRequest;

    public static bool IsProcessingNewIllustrationRequest
    {
        get { return _isProcessingNewIllustrationRequest; }
        set { _isProcessingNewIllustrationRequest = value; }
    }

然后在MVC中:

    public ActionResult CreateNewApplication()
    {
        if (!Global.IsProcessingNewIllustrationRequest)
        {
            Global.IsProcessingNewIllustrationRequest = true;

            // DO WORK... RUN CODE
            Global.IsProcessingNewIllustrationRequest = false;
            return View("Index", model);
        }
        else
        {
            // DISPLAY A MESSAGE THAT ANOTHER REQUEST IS IN PROCESS
        }
    }

但是似乎代码无法正常工作,因为两个线程(Chrome和Firefox)仍然可以同时执行代码.

But if seems as if the code isn't working, because both threads(Chrome & Firefox) still executes the code at the same time.

已更新

private Object thisLock = new Object();     
public ActionResult CreateApplication()
        {
            ILog log = LogManager.GetLogger(typeof(Global));
            string aa = this.ControllerContext.HttpContext.Session.SessionID;
            log.Info("MY THREAD: " + aa);

            lock (thisLock)
            {
                Thread.Sleep(8000);

                DO SOME STUFF

            }
        }

即使使用日志,线程2(Firefox会话)仍会进入代码,而会话1(Chrome)正在使用锁执行该代码.我想念什么?

Even with the log, thread 2 (Firefox session) still goes into the code while session1 (Chrome) is executing it with the lock. What am I missing?

推荐答案

我可以看到两个明显的原因,导致此代码无法满足您的要求.

I can see two obvious reasons why this code won't do what you want.

问题1:它不是线程安全的.每当有人连接到您的服务器时,该请求就会在一个线程中运行,并且如果有多个请求进入,那么多个线程都将同时在运行.几个线程可以很好地同时读取该标志,所有线程都看到它是错误的,因此所有线程都进入它们的if块并都完成了工作,而这正是您要避免的事情.

Problem #1: It's not threadsafe. Every time someone connects to your server, that request is going to run in a thread, and if multiple requests come in, then multiple threads are all going to be running at the same time. Several threads could very well read the flag at the same time, all see that it's false, and so all enter their if block and all do their work, which is exactly what you're trying to prevent.

这是一个比赛条件"(结果取决于谁赢得比赛).布尔变量不足以解决竞争条件.

This is a "race condition" (the results depend on who wins the race). Boolean variables aren't enough to solve a race condition.

有很多方法可以实际解决此问题.最好的办法是删除共享状态,以便每个线程可以完全独立于其他线程运行,而无需将其他线程锁定在外.但我认为您已经考虑过了,这是不实际的.接下来要看的是互斥体监视器.监视器使用起来稍微简单一些,但是只有两个线程实际上都在相同的应用程序域和相同的进程中时,它们才起作用.那带我去...

There are a bunch of ways to actually fix this problem. The best would be to remove the shared state, so each thread can run completely independently of the others and there's no need to lock the others out; but I'll assume you've already considered that and it's not practical. The next things to look at are mutexes and monitors. Monitors are a little simpler to use, but they only work if both threads are actually in the same appdomain and the same process. That brings me to...

问题2:两个线程可能不在同一进程中. IIS的最新版本将启动多个单独的辅助进程来处理Web请求.每个进程都有其自己的地址空间,这意味着每个进程(从技术上讲,每个appdomain 内的每个进程)都有自己的全局"变量副本!

Problem #2: The two threads might not be in the same process. Recent versions of IIS will launch multiple separate worker processes to handle Web requests. Each process has its own address space, meaning each process (technically each appdomain within each process) has its own copy of your "global" variable!

实际上,如果您要建立一个流量很高的网站,则不同的工作进程甚至可能不在同一台计算机上运行.

In fact, if you're building a really high-traffic Web site, the different worker processes may not even run on the same computer.

工作流程是您最有可能的罪魁祸首.如果您遇到了竞争问题,那么这个问题将非常罕见(在出现问题时甚至更难以调试).如果您每次都看到它,那我的钱就花在多个工作程序上.

Worker processes are your most likely culprit. If you were facing a race condition, the problem would be incredibly rare (and even more incredibly hard to debug when it did come up). If you're seeing it every time, my money is on multiple worker processes.

让我们假设所有工作进程都将在同一台服务器上(毕竟,如果您的预算足以使应用程序可以扩展到多个Web服务器,那么您将比我更了解多线程编程)做).如果所有内容都在同一服务器上,则可以使用名为 Mutex 跨不同的appdomain和进程进行协调.像这样:

Let's assume that all the worker processes will be on the same server (after all, if you had the kind of budget that required apps that can scale out to multiple Web servers, you would already know way more about multithreaded programming than I do). If everything's on the same server, you can use a named Mutex to coordinate across different appdomains and processes. Something like this:

public static Mutex _myMutex = new Mutex(false, @"Global\SomeUniqueName");

public ActionResult CreateNewApplication()
{
    if (_myMutex.WaitOne(TimeSpan.Zero))
    {
        // DO WORK... RUN CODE
        _myMutex.ReleaseMutex();
        return View("Index", model);
    }
    else
    {
        // DISPLAY A MESSAGE THAT ANOTHER REQUEST IS IN PROCESS
    }
}

如果另一个线程拥有互斥锁,WaitOne(TimeSpan.Zero)将立即返回.如果您希望另一个线程通常会很快完成,则可以选择传递非零时间跨度.那么它将在放弃之前等待很长时间,这将给用户带来比立即失败并显示请稍后重试"错误消息更好的体验.

The WaitOne(TimeSpan.Zero) will return immediately if another thread owns the mutex. You could choose to pass a nonzero timespan if you expect that the other thread will usually finish quickly; then it will wait that long before giving up, which would give the user a better experience than failing instantly into a "please try again later" error message.

这篇关于ASP.NET中的全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆