Зависает программа WPF BeginInvoke
Возникла проблема:
Есть сервер и 2 клиента. Сервер, периодически дергает Event. И клиенты должны обрабатывать событие. Когда один клиент - все работает отлично.
Но в случае если 2-3 клиента, при обновлении информации, когда один обновляемый пункт находится у двух клиентов на экране, программа переодически зависает и выдает вот такую странную ошибку:
The CLR has been unable to transition from COM context 0x1f8ac0 to COM context 0x1f8c30 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.
Программа полностью написана на WPF + C#.
Поток, который вызывает эту ошибку запускается:
Код:
System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(CheckACChanges));
Сам поток:
Код:
DispatcherOperation dispOperation = null;
//while ((sender as ManualResetEvent).WaitOne())
//while(true)
{
#region Changed Item processing
if (m_changedItem != null)
{
LogFile.Log.WriteToLog("Получена новая информация о товаре");
lock (m_changedItem)
{
switch (m_changedItem.Operation)
{
case Operation.ADDED:
dispOperation = _tvContentStruct.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
for (int i = 0; i < _tvContentStruct.Items.Count; i++)
{
if (AddItem(_tvContentStruct.Items as Node, m_changedItem as Item))
break;
}
UpdateCategoryCaption();
});
break;
case Operation.UPDATED:
LogFile.Log.WriteToLog("BeginInvoke товара, ОБНОВЛЕНИЕ");
dispOperation = _tvContentStruct.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action (delegate
{
LogFile.Log.WriteToLog("Внутри BeginInvoke Товара");
for (int i = 0; i < _tvContentStruct.Items.Count; i++)
{
if (UpdateItem(_tvContentStruct.Items as Node, m_changedItem as Item))
break;
}
// UpdateCategoryCaption();
}));
break;
case Operation.DELETED:
dispOperation = _tvContentStruct.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
for (int i = 0; i < _tvContentStruct.Items.Count; i++)
if (DeleteItem(_tvContentStruct.Items as Node, m_changedItem as Item))
break;
UpdateCategoryCaption();
});
break;
}
int waitCount = 0;
if (dispOperation != null)
{
dispOperation.Completed += new EventHandler(dispOperation_Completed);
LogFile.Log.WriteToLog(String.Format("Ожидание окончания работы диспетчера. Текущее состояние диспетчера {0}", dispOperation.Status));
while (dispOperation.Status != DispatcherOperationStatus.Completed)
{
Thread.Sleep(500);
if (waitCount > 5)
{
//dispOperation.Abort();
//dispOperation.Dispatcher.Thread.Abort();
break;
}
waitCount++;
}
}
LogFile.Log.WriteToLog(String.Format("Информация о диспетчере: Состояние: {0}\n Результат: {1}\n\n\n\n\n", dispOperation.Status, dispOperation.Result));
//while ((sender as ManualResetEvent).WaitOne())
//while(true)
{
#region Changed Item processing
if (m_changedItem != null)
{
LogFile.Log.WriteToLog("Получена новая информация о товаре");
lock (m_changedItem)
{
switch (m_changedItem.Operation)
{
case Operation.ADDED:
dispOperation = _tvContentStruct.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
for (int i = 0; i < _tvContentStruct.Items.Count; i++)
{
if (AddItem(_tvContentStruct.Items as Node, m_changedItem as Item))
break;
}
UpdateCategoryCaption();
});
break;
case Operation.UPDATED:
LogFile.Log.WriteToLog("BeginInvoke товара, ОБНОВЛЕНИЕ");
dispOperation = _tvContentStruct.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action (delegate
{
LogFile.Log.WriteToLog("Внутри BeginInvoke Товара");
for (int i = 0; i < _tvContentStruct.Items.Count; i++)
{
if (UpdateItem(_tvContentStruct.Items as Node, m_changedItem as Item))
break;
}
// UpdateCategoryCaption();
}));
break;
case Operation.DELETED:
dispOperation = _tvContentStruct.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
for (int i = 0; i < _tvContentStruct.Items.Count; i++)
if (DeleteItem(_tvContentStruct.Items as Node, m_changedItem as Item))
break;
UpdateCategoryCaption();
});
break;
}
int waitCount = 0;
if (dispOperation != null)
{
dispOperation.Completed += new EventHandler(dispOperation_Completed);
LogFile.Log.WriteToLog(String.Format("Ожидание окончания работы диспетчера. Текущее состояние диспетчера {0}", dispOperation.Status));
while (dispOperation.Status != DispatcherOperationStatus.Completed)
{
Thread.Sleep(500);
if (waitCount > 5)
{
//dispOperation.Abort();
//dispOperation.Dispatcher.Thread.Abort();
break;
}
waitCount++;
}
}
LogFile.Log.WriteToLog(String.Format("Информация о диспетчере: Состояние: {0}\n Результат: {1}\n\n\n\n\n", dispOperation.Status, dispOperation.Result));
По логам видно, что Диспетчер всегда находится в сстоянии Pending...закономерности никакой нет, это может произойти при первом или нном обновлении... Единственное, что удалось заметить. что это зависание происходит только тогда, когда фокус двух приложений находится на одном и том же товаре...в списке.
ЗЫ: В релизной версии оба клиента просто зависают...вместе с самим сервером.