mainthread не ждет конца параллельного. foreach - PullRequest
0 голосов
/ 20 февраля 2019

Я схожу с ума из-за проблемы в моем коде.

Я работаю с библиотекой с именем "Interop.Automation.dll", которая предоставляет событие "dataChange", к которому я прикрепил обработчик.

В определенный момент в моем коде mainThread запускает Parallel.Foreach

Parallel.ForEach(aOPCItems.Cast<OPCItem>().ToList(), (item) =>
{
    if (item.CanonicalDataType > 8000) 
    {
        return;
    }

    IOPCItem itemTemp = new AutomationItem(item);
    Monitor.Enter(listOPCItems);
    listOPCItems.Add(itemTemp);
    Monitor.Exit(listOPCItems);

    Monitor.Enter(opcItemDict);
    if (!opcItemDict.ContainsKey(item.ClientHandle))
    {
        opcItemDict.Add(item.ClientHandle, itemTemp);
    }
    Monitor.Exit(opcItemDict);

});

MainThread начинает выполнение тела Parallel.Foreach для некоторых элементов.

Во время этогоParallel.Foreach событие dataChage, по-видимому, запускается, и mainthread отправляется на выполнение кода обработчика.

Нет кода в Parallel.Foreach, который может вызвать событие.

Остановка выполнения с точкой останова в коде обработчика. Я вижу, что mainthread там работает, а worksThreads работает в теле Paralle.Foreach.

Когда mainThread завершает работу в коде обработчикаи workingThread завершает работу в теле Parallel.Foreach, после чего mainThread продолжается с кодом в Parallel.Foreach.

Это нормальное поведение, если mainThread оставляет Parallel.Foreach для выполнения кода обработчика ичем вернуть обратно?

Это стек вызовов во время mainThread выполняет код обработчика

Это код в конструкторе AutomationItem

private string _itemName;
private OPCItem _item;
private object _value;
private string _quality;

Array ItemServerHandles = Array.CreateInstance(typeof(Int32), 2);
int cancelID;
int transactionID = 1;

public AutomationItem(OPCItem item)
{
     _item = item;
     if (item.Quality == 192)
     {
         _quality = "Good";
     }
     else
     {
         _quality = 
((OPCQuality)item.Quality).ToString().Replace("OPCQuality", String.Empty);
     }
     _itemName = item.ItemID;
     ItemServerHandles.SetValue(item.ServerHandle, 1);
 }

РЕДАКТИРОВАТЬ: Я заменил Parallel.Foreach на обычный foreach, поведение сохраняется.Трассировка стека аналогична.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...