【问题标题】:Threading problem with some old code一些旧代码的线程问题
【发布时间】:2011-07-25 18:53:03
【问题描述】:

我正在处理一个最近从 .net 1.1 升级到 .net 4.0 的项目。我们从自定义的“ThreadPool”类中得到一个错误(是的,有人觉得有必要自己编写),现在我想知道它可能是什么。

错误是从以下代码抛出的:

    private void Submit(WorkItem work)
    {
        this.AdjustPoolSize();

        lock (this.workQueue.SyncRoot)
        {
        //Monitor.Enter(workQueue);
        this.workQueue.Enqueue(work);
            Monitor.Pulse(this.workQueue.SyncRoot);
        //Monitor.Exit(workQueue);
        }
    }

注释代码是我收到代码的方式。不幸的是,我对这个项目一无所知,只是来解决这个问题。我们看到的错误是:

System.Threading.SynchronizationLockException was unhandled by user code
  Message=Object synchronization method was called from an unsynchronized block of code.
  Source=mscorlib
  StackTrace:
       at System.Threading.Monitor.ObjPulse(Object obj)
       at System.Threading.Monitor.Pulse(Object obj)
       at CustomThreadPoolObject.Submit(WorkItem work) in D:\...\Threading.cs:line 1438
       at CustomThreadPoolObject.Submit(WaitCallback callback, Object state) in D:\...\Threading.cs:line 1349
       at SomeGroupProcessFunctionality.Submit(PooledThread thread, TaskInfo task, String appServer, Hashtable batchHandleTable) in D:\...\ProcessGroup.cs:line 143
       at System.Runtime.Remoting.Messaging.Message.Dispatch(Object target, Boolean fExecuteInContext)
       at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)
  InnerException: 

从表面上看,某些东西被触发为“可用”,而实际上它不是。我尝试用谷歌搜索并找到 http://bbellomo.blogspot.com/2007/03/object-synchronization-method-was.html 但这对我没有太大帮助,因为我不太了解他的问题和解决方案。

希望有人能给我一些提示。

谢谢!

【问题讨论】:

  • 将线程应用程序从 1.1 更新到 4.0,而不是重新处理线程?这似乎是核心问题所在。
  • workQueue的类型是什么?
  • 当您Pulse 在您当前不拥有其监视器的对象上时,通常会引发异常。鉴于周围的lock 语句显式进入this.workQueue.SyncRoot 的监视器,这很难完成。 Enqueue() 是什么样的? workQueue 是什么类型? (如果是自定义类型,请确保其 SyncRoot 实现返回一致的对象。)
  • 这里有些奇怪:原始代码在workQueue 上输入锁并在workQueue.SyncRoot 上发出脉冲:这是错误的,应该会触发您看到的异常。但是,您更正的代码对我来说似乎有效。
  • 抱歉,我的网络出现故障。 Workqueue 是一个队列对象(.net 类型),而 enqueue 是一种方法。我真的很想要一些想法,这样我就可以完成这个项目。

标签: .net multithreading .net-4.0 thread-safety


【解决方案1】:

由于您使用的是自己的线程池机制。那么异常可能是因为线程在lock 之后和调用Monitor.Pulse 之前发生了变化。根据 msdn,如果:

调用线程不拥有指定对象的锁。

编辑: 或者您在第一次锁定后锁定在不同的线程中,“也许在生产者线程上,将出队 WorkItem 并在池中启动它们,您正在调用 lock (this.workQueue.SyncRoot) " 在到达 Monitor.Pulse(this.workQueue.SyncRoot); 之前,在那个线程上。

【讨论】:

  • 最终有一个线程锁定了隐藏在代码深处的“对象”。改为锁定 SyncRoot,一切都很好。
  • 很高兴你找到它。这个错误通常很难找到;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
相关资源
最近更新 更多