Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 静态类和多个同时请求_C#_Asp.net - Fatal编程技术网

C# 静态类和多个同时请求

C# 静态类和多个同时请求,c#,asp.net,C#,Asp.net,假设我有一个静态助手类,我在web应用程序中经常使用它。假设应用程序在一段持续的时间内每秒接收大约20个请求,并且神奇的是,有两个请求要求静态类以完全相同的纳秒进行一些工作 发生这种情况时会发生什么 为了提供一些上下文,该类用于执行linq到sql查询:它接收一些参数,包括UserID,并返回一个自定义对象列表 谢谢。它会以一种令人讨厌的方式崩溃(如果您这样做是为了共享状态),请避免在Web应用程序中这样做。。。或者使用锁交替保护读/写操作: 但老实说,除非你真的必须使用静态,否则你真的应该避

假设我有一个静态助手类,我在web应用程序中经常使用它。假设应用程序在一段持续的时间内每秒接收大约20个请求,并且神奇的是,有两个请求要求静态类以完全相同的纳秒进行一些工作

发生这种情况时会发生什么

为了提供一些上下文,该类用于执行linq到sql查询:它接收一些参数,包括UserID,并返回一个自定义对象列表


谢谢。

它会以一种令人讨厌的方式崩溃(如果您这样做是为了共享状态),请避免在Web应用程序中这样做。。。或者使用锁交替保护读/写操作:


但老实说,除非你真的必须使用静态,否则你真的应该避免使用静态。如果你真的必须使用静态,你必须非常小心你的锁定策略,并对其进行破坏性测试,以确保你已经成功地将读写操作彼此隔离开来

你必须确保你的方法是线程安全的,所以不要使用静态属性来存储任何类型的状态。如果在静态方法中声明新对象,则没有问题,因为每个线程都有自己的对象。

这完全取决于“某些工作”的含义。如果它不涉及任何共享状态,那就完全可以了。如果它需要访问共享状态,您需要了解如何以线程安全的方式处理它


一般的经验法则是,对于静态方法,类的公共API应该是线程安全的,但对于实例方法,则不必是线程安全的——通常,任何一个实例都只能在单个线程中使用。当然,这取决于您的类正在做什么,并且取决于静态类是否具有任何状态(即,在所有调用中共享静态变量)。如果没有,那就好了。如果是这样,那就不好了。示例:

// Fine
static class Whatever
{
    public string DoSomething() {
        return "something";
    }
}

// Death from above
static class WhateverUnsafe
{
    static int count = 0;
    public int Count() {
        return ++count;
    }
}
您可以使用锁使第二个工作正常,但随后会引入死锁和并发问题

我用静态类构建了大量web应用程序,但它们从来没有任何共享状态

发生这种情况时会发生什么

如果您的方法是线程安全的,那么它们是线程安全的,并且发生的情况是它们很可能会工作。如果这些静态方法依赖于某个共享状态,而您尚未同步访问此状态,则此共享状态很可能会损坏。但您不需要在同一纳秒内通过20个请求来破坏您的共享状态。如果不同步,2就足够了

因此,静态方法本身并不是邪恶的(事实上,它们不是单元测试友好的,但这是另一个主题),在多线程环境中,它们的实现方式才是重要的。所以你应该让它们线程安全


更新:

因为在您提到的注释部分中,只要静态方法中使用的所有变量都是本地变量,LINQ-TO-SQL就是线程安全的。例如:

public static SomeEntity GetEntity(int id)
{
    using (var db = new SomeDbContext())
    {
        return db.SomeEntities.FirstOrDefault(x => x.Id == id);
    }
}

不可阻挡的力量停止了,不可移动的物体移动了。关于读和写,谁说了什么?没有证据表明这是在使用任何共享状态。@Jon:假设是一件危险的事情;p我假设OP这样做是为了在线程之间共享状态。我更新了我的帖子来反映这一点,就像你发表评论一样;这是个坏主意吗?类是否应该是静态的,并且在每次使用时都被实例化?@frenchie:这是一个相当模糊的术语——请阅读链接的博客文章。但用hand wavy术语来说,它意味着“如果多个线程同时调用同一代码,那么坏事情就不会发生”在某个特定上下文中。@frenchie:Linq2SQL数据上下文本身不是线程安全的。只要每个helper调用初始化自己的上下文,并且您不访问任何其他静态共享资源,您就应该fine@frenchie:您应该在方法内创建新的LINQ to SQL DataContext,而不是将其存储在静态变量中。您有在多个线程之间共享的变量吗?(您有哪些静态变量?)是的,该类在中创建一个新的datacontext。我决定将类从静态更改为实例化调用类中的对象。也就是说,以后肯定不会有任何OOO PSSS错误。如果两个或多个线程同时执行一个方法,则需要确保对共享资源的访问受到控制,否则会出现意外行为。这是线程安全termOk的一种恢复;我将静态类用于linq到sql查询。如果我这样做,我会完蛋吗?我在想,但是保持类的静态,我节省了实例化对象的成本。我怀疑你会担心对象实例化的成本。它并不昂贵,而且我不确定Linq2Sql是否是线程安全的。静态类用于linq到sql查询。坏主意?@frenchie,只要这个静态类不依赖于非线程安全的静态资源,你就可以了。@frenchie,我已经更新了我的答案,提供了一个可以与Linq-to-SQL一起使用的线程安全方法的示例。好的,很酷,我的类就是这样编写的。如果我想变得超级安全,我应该花10-15分钟转换成类实例化吗?@frenchie,是的,你应该花10-15分钟将它转换成一个非静态类,你会把它放在DAL层中。但您不应该这样做,因为此实现不安全。您应该这样做,以削弱调用代码和数据访问代码之间的耦合。