Remarque: cette erreur se trouve à la ligne WaitHandle.WaitAll (doneEvents); J'utilise un standard projet WPF.
private void Search()
{
const int CPUs = 2;
var doneEvents = new ManualResetEvent[CPUs];
// Configure and launch threads using ThreadPool:
for (int i = 0; i < CPUs; i++)
{
doneEvents[i] = new ManualResetEvent(false);
var f = new Indexer(Paths[i], doneEvents[i]);
ThreadPool.QueueUserWorkItem(f.WaitCallBack, i);
}
// Wait for all threads in pool
WaitHandle.WaitAll(doneEvents);
Debug.WriteLine("Search completed!");
}
pdate: La solution suivante ne fonctionne pas pour les applications WPF! Il n'est pas possible de remplacer l'attribut d'application principal par MTAThreadAttribute. Cela entraînera l'erreur suivante:
Erreur: "WaitAll pour plusieurs descripteurs sur un thread STA n'est pas pris en charge."
Qu'en est-il de l'utilisation des tâches pour réaliser votre threading pour vous?.
http://msdn.Microsoft.com/en-us/library/system.threading.tasks.task.aspx
var task1 = Task.Factory.StartNew(() => DoSomeWork());
var task2 = Task.Factory.StartNew(() => DoSomeWork());
var task3 = Task.Factory.StartNew(() => DoSomeWork());
Task.WaitAll(task1, task2, task3);
En fait, j'utilise ce qui suit pour remplacer WaitHandle.WaitAll (doneEvents);
foreach (var e in doneEvents)
e.WaitOne();
Utilisez un ManualResetEvent
et attendez-le. Conservez également une variable TaskCount définie sur le nombre de threads de travail que vous démarrez, utilisez Interlocked.Decrement
dans le code de thread de travail comme la toute dernière action du travailleur et signaler l'événement si le compteur atteint zéro, par exemple.
// other worker actions...
if (Interlocked.Decrement(ref taskCount) == 0)
doneEvent.Set();
Je voudrais refactoriser votre code pour utiliser la classe CountdownEvent
à la place.
private void Search()
{
const int CPUs = 2;
var done = new CountdownEvent(1);
// Configure and launch threads using ThreadPool:
for (int i = 0; i < CPUs; i++)
{
done.AddCount();
var f = new Indexer(Paths[i], doneEvents[i]);
ThreadPool.QueueUserWorkItem(
(state) =>
{
try
{
f.WaitCallBack(state);
}
finally
{
done.Signal();
}
}, i);
}
// Wait for all threads in pool
done.Signal();
done.Wait();
Debug.WriteLine("Search completed!");
}
utilisez quelque chose comme ceci:
foreach (ITask Task in Tasks)
{
Task.WaitHandle = CompletedEvent;
new Thread(Task.Run).Start();
}
int TasksCount = Tasks.Count;
for (int i = 0; i < TasksCount; i++)
CompletedEvent.WaitOne();
if (AllCompleted != null)
AllCompleted(this, EventArgs.Empty);