Потоковая проблема со старым кодом - PullRequest
4 голосов
/ 25 июля 2011

Я работаю над проектом, который недавно обновился с .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 голос
/ 26 июля 2011

Поскольку вы используете свой собственный механизм пула потоков.Тогда исключение, вероятно, потому что поток изменился после lock и до того, как вы вызовете Monitor.Pulse.в соответствии с msdn это исключение выдает Pulse, если:

Вызывающему потоку не принадлежит блокировка для указанного объекта.

Редактировать: Или вы блокируете другой поток после вашей первой блокировки, «возможно, в потоке производителя, который выведет из очереди WorkItem и запустит их в пуле, вы вызываете lock (this.workQueue.SyncRoot)» в этом потоке, прежде чем достигнуть Monitor.Pulse(this.workQueue.SyncRoot);.

...