代码之家  ›  专栏  ›  技术社区  ›  Paul Creasey

ASP MVC-Comet/Reverse Ajax/Push-此代码是线程安全的吗?

  •  0
  • Paul Creasey  · 技术社区  · 15 年前

    我正在尝试实现Comet风格的特性,方法是在服务器上轮询数据的变化,并保持连接打开,直到有东西需要响应为止。

    首先,我的控制器上有一个静态变量,用于存储上次更新数据的时间:

    public static volatile DateTime lastUpdateTime = 0;
    

    所以每当我轮询的数据改变时,这个变量就会改变。

    然后我有一个操作,它将数据作为参数进行最后一次检索:

    public ActionResult Push(DateTime lastViewTime)
    {
        while (lastUpdateTime <= lastViewTime)
        { 
            System.Threading.Thread.Sleep(10000);
        }
        return Content("testing 1 2 3...");
    }
    

    所以如果 lastUpdateTime 小于或等于 lastViewTime ,我们知道没有新的数据,我们只是将请求保持在一个循环中,保持连接打开,直到有新的信息,然后我们可以将其发送回客户机,客户机将处理响应,然后发出新的请求,因此连接基本上总是打开的。

    这看起来不错,但我担心线程安全,可以吗?LastUpdateTime是否需要标记为volatile?有更好的方法吗?

    谢谢

    编辑:也许我应该在更新时间值时使用锁对象

    private static object lastUpdateTimeLock = new object();
    
    ..
    
    lock (lastUpdateTimeLock)
    {
        lastUpdateTime = DateTime.Now;
    }
    
    2 回复  |  直到 14 年前
        1
  •  3
  •   Jerod Venema    15 年前

    关于您最初的问题,您必须小心日期时间,因为它们是.NET运行时中的实际对象。只有少数数据类型可以在本地访问(如ints、bools),而不需要锁定(假设您没有使用interlocked)。如果你想避免日期时间的问题, 您可以将标记作为一个长标记,并使用联锁类来管理它们。

    也就是说,如果您在.NET应用程序中寻找Comet功能,那么不幸的是,您必须比这里的功能做得更远。IIS/ASP.NET不会像您现在使用的方法那样进行扩展;您甚至会在达到100个用户之前达到限制。除其他之外,您必须切换到使用异步处理程序,并为传入的请求实现一个自定义的绑定线程池。

    如果您真的想要一个经过测试的ASP.NET/IIS解决方案,请签出 WebSync 它是专门为此设计的一个完整的Comet服务器。

        2
  •  1
  •   David Hogue    15 年前

    老实说,我关心的是保持打开的连接数和空的while循环。你的连接可能很好,但我肯定想做一些负载测试来确定。

    这个 while (lastUpdateTime <= lastViewTime) {} 好像应该有一个 Thread.Sleep(100) 或者里面的东西。否则我会认为它会不必要地消耗大量的CPU周期。

    我周围好像不需要锁 lastUpdateTime = DateTime.Now 因为前一个值无关紧要。如果是的话 lastUpdateTime = lastUpdateTime + 1 或者别的什么 也许吧 是这样的。