7

我是一名自学成才的 C# 程序员,在对事物有非常透彻的理解时,我在这里和那里错过了一些东西,现在我偶然发现了一些我无法找到答案的东西所以。我试图更好地理解 C# 中的线程安全,但让我先指​​定上下文。

我目前正在开发一个 Windows 服务,它会根据驻留在 SQL Server 数据库中的时间表启动并执行一些监视工作。它将通过向多个“客户端服务器”发出 http 请求来监视某些服务器,安装在这些服务器上的客户端将响应请求的信息。

由于此监视器服务可能会变得非常繁忙,因此我已将其设置为在计划执行工作时将每个“计划指令”粘贴在新线程中。这是为了确保我的计时器一直运行良好,准备好启动下一个指令到下一个“客户端服务器”。

每条指令的一部分是必须登录数据库,它已成功执行以及响应是什么等等。现在我的监视器服务中有 a public static class Logger,我相信这很方便,因为我现在可以Logger.Log(... )在需要记录事物时轻松地以这种方式调用它。此日志记录在此类中通过 EF 发生在 SQL Server 数据库中。

对我来说,这一切听起来真的很酷,我对它的工作方式很满意,但我还没有对任何东西进行负载测试。所有这一切的问题是我的大脑告诉我,因为我的记录器类是静态的 -根据我的理解,因此它只实例化一次?- 如果超过 1 个线程试图同时调用Logger.Log(.. ),我的监控服务会发生坏事。

这里有人可以启发我吗?我的想法是对还是错?如果你知道答案,请解释清楚,因为我很想理解它。:)

更新:

感谢到目前为止的回复,事情变得越来越清楚,因为人们正在询问有关该Log方法的更多细节,而我目前不在我的开发 PC 上,我将尝试更详细地解释它的工作方式。

Log方法所做的只是根据一些先前实例化的对象的数据,通过 EF 向 SQL 数据库添加一条记录,这些对象作为参数传递给该方法。数据库上下文被实例化为静态类上的静态私有变量。这样做的原因是我不必在重载中继续使用 using 语句。

4

3 回答 3

3

static 提供危险代码的机会,但不保证。如果您使用的是static类/方法,则必须小心不要使用任何实例数据。

在你的情况下这意味着什么?基本上,您希望在方法中实例化您DbContextLog方法,进行日志记录,然后DisposeDbContext将使用情况包装在using语句中)。只要不共享实例数据,就可以了。

但是,如果您在静态构造函数中执行某些操作或使用类级变量,则可能会产生问题。

编辑:在您的特定情况下,您不应该DbContext在所有线程中共享。在这里查看有关 a 的正确范围的讨论DbContext。它应该在每个方法中实例化。

该博客条目陈述了以下内容(并提供了解释):

大多数 [这些考虑因素] 倾向于指向不共享的短命上下文。

所以这是我推荐的经验法则。

于 2013-10-14T19:19:19.640 回答
3

每个方法,无论是静态的还是虚拟的,都会有自己的框架,所以不涉及线程问题。问题出现在方法实现中:一些静态方法会使用静态变量或静态资源,而且它们都是同一个管道,你会遇到竞争条件。但是在静态方法中声明的局部变量不是静态的,所以如果你的方法不修改静态变量或资源,你会没事的。

于 2013-10-14T19:27:19.373 回答
3

Logger关于线程安全,您的课程的文档是怎么说的?静态类或方法本身并没有什么线程不安全的。

如果您调用的方法或属性,无论它是否是静态的

  • 引用相关方法的本地变量(例如,不引用任何实例或静态成员),并且
  • 创建自己需要与之协作的任何其他类的实例

你应该是线程安全的。请注意,在其他类中调用的任何方法或属性同样必须是线程安全的。

于 2013-10-14T19:29:30.067 回答