【问题标题】:c# lock does not work (?)c#锁不起作用(?)
【发布时间】:2016-07-04 19:24:46
【问题描述】:

我有以下锁定场景,它似乎偶尔会错过一个锁,让 2 个代码实例并行运行。非常感谢您在分析/修复代码方面的帮助。

public delegate void _D(A a);      

namespace ExternalDll {
    public event _D D;
}

namespace MainSpace {
    ExternalDll _externalDll;
    public static object lockObj = new object();
    public static int counter = 0;
    .
    .
    _externalDll.D += new _D(myEventHandler);
    .
    .
    void myEventHandler(A a) {
        lock (lockObj) {
            counter++;
            // do staff, printouts, etc.
            Console.WriteLine("First={0}\n", counter);
            // do other staff
            Console.WriteLine("Second={0}\n", counter);
        }
    }
}

ExternalDll 是一个 dll 文件,它接收带有信息 a(类型 A)的网络通信。它以 a 作为输入调用事件 D。

主命名空间将 myEventHandler 注册到由 ExternalDll 触发的事件 D。 在 myEventHanlder 内部有一个锁,因此预期的行为是 lock 部分内的代码在任何时候都不会执行多次。

但是,在运行应用程序时,有时会遇到锁定代码“并行”执行两次的情况。例如,我可能会看到如下打印输出:

First=0
First=1
Second=0
Second=1

这种情况尤其发生在突发网络事件在很短的持续时间 (

我的问题/要求是:

  • 是什么导致 lock 语句出现这种错误行为。允许锁定代码的 2 个实例?

  • 如何改进代码以提供所需的锁定行为。

谢谢,

-摩西。

【问题讨论】:

  • 它正在锁定变量theLock,但我没有看到分配给它的任何值,你不希望它锁定lockObj吗?
  • 是否还有其他代码要写入计数器?
  • 探矿者上面所说的,您的示例代码使用“theLock”,但暗示它应该使用“lockObj”。也许清理一下你的例子?除此之外,“// do other staff”是否会在事件处理程序完成之前调用任何会导致另一个回调的东西?
  • 那是一个错字...编辑了代码。谢谢
  • 没有其他代码写入计数器。仅显示增量。 “做员工”部分是纯粹的计算。它不会调用任何会导致另一个回调的东西。

标签: c# multithreading


【解决方案1】:

不知道说什么。一个猜测是正在创建两个应用程序域,因为您使用的东西会产生多个应用程序域,例如Asp.net 有时会为 http 模块执行此操作。

【讨论】:

  • 是的,很可能 OP 多次启动他的应用程序。
  • 我的应用程序是普通计算,而不是 Web 服务器或类似的东西。我在运行时只看到一个控制台窗口。
  • 也许还可以打印 lockObj 的地址以查看 - 可能是编组器在做一些奇怪的事情。
  • Ammm...如何打印该地址?打印 (int)&lockObj 的值会导致编译错误 CS0208(“无法获取托管类型“对象”的地址、大小或声明指向托管类型“对象”的指针”)...(即使在不安全的上下文中)
  • 固定对象以获得 GCHandle:dzone.com/articles/net-memory-control-use-gchandl 然后在 GCHandle 上有一个方法。作为作弊,我有时会在 Object 上使用哈希码,因为它在对象之间大多不同,但不能保证唯一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多