На одноядерных машинах обнаружил очень интересную проблему, которая поставила меня в тупик:
Если из нитки, работающей в ThreadPool поставить в очередь метод при помощи QueueUserWorkItem и после этого запустить бесконечное ожидание event'а, то метод никогда не будет запущен.
Проблема повторяется как при использовании managed кода (пример на C#), так и при использовании unmanaged кода (пример на delphi).
прроблема повторяется только если в системе одно ядро (например на виртуальной машине).
Вот тестовый пример на C#:
namespace TP2003_cs
{
using System;
using System.Threading;
public class TP2003
{
static EventWaitHandle event1 = new EventWaitHandle(false, EventResetMode.ManualReset);
static EventWaitHandle event2 = new EventWaitHandle(false, EventResetMode.ManualReset);
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(WorkItem1);
EventWaitHandle.WaitAll(new EventWaitHandle[] { event1, event2 });
}
static void WorkItem1(object state)
{
WriteLine("WorkItem1 - begin");
ThreadPool.QueueUserWorkItem(WorkItem2);
WriteLine(event2.WaitOne(1000) ? "event2 - signaled" : "event2 - timeout");
event1.Set();
WriteLine("WorkItem1 - end");
}
static void WorkItem2(object state)
{
WriteLine("WorkItem2 - begin");
WriteLine("event2 - set");
event2.Set();
WriteLine("WorkItem2 - end");
}
static void WriteLine(string str)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + ": " + str);
}
}
}
выдаются следующие результаты:
На многопроцессорном компьютере:
3: WorkItem1 — begin
4: WorkItem2 — begin
4: event2 — set
4: WorkItem2 — end
3: event2 — signaled
3: WorkItem1 — end
Как видно из лога WorkItem2 запускается в новой нитке (ThreadID = 4).
Результат на однопроцессорном компьютере:
3: WorkItem1 — begin
3: event2 — timeout
3: WorkItem1 — end
3: WorkItem2 — begin
3: event2 — set
3: WorkItem2 — end
Как видно из лога WorkItem2 запускается в той же самой нитке после завершения WorkItem1.
Проверял на компьютере с физически одним процессором под Win 2003, на VirtualPC под Win XP, Win 2003, Win 7.
Подскажите, может кто-то сталкивался с данной проблемой и знает каким образом можно попытаться её обойти?