Мне удалось победить (: P) асинхронного монстра в серебряном свете, вот так:
var ctx = new ModelEntities(new Uri("http://localhost:2115/Data.svc"));
ManualResetEvent m1 = new ManualResetEvent(false);
ManualResetEvent m2 = new ManualResetEvent(false);
var q1 = (DataServiceQuery<Department>)(from e in ctx.Department select e);
var q2 = (DataServiceQuery<Person>)(from e in ctx.Person select e);
Department[] r1 = null;
Person[] r2 = null;
q1.BeginExecute(r =>
{
try { r1 = q1.EndExecute(r).ToArray(); }
finally { m1.Set(); }
}, null);
q2.BeginExecute(r =>
{
try { r2 = q2.EndExecute(r).ToArray(); }
finally { m2.Set(); }
}, null);
ThreadPool.QueueUserWorkItem((o) =>
{
WaitHandle.WaitAll(new WaitHandle[] { m1, m2 });
// do your thing..
});
Основной идеей является создание потока официанта (последний блок), который будет иметь ссылки на объекты ожидания. НЕ помещайте свой вызов WaitAll в метод / поток вызывающего абонента, потому что это приведет к тупику, как другие упоминали ранее на этом сайте или других сайтах.
Взаимная блокировка возникает из-за того, что потоки не запускаются до тех пор, пока метод не завершится, а метод не заканчивается, потому что вызов WaitAll ожидает завершения дочерних потоков.
Не в моем случае выше, однако, потому что WaitAll находится на другом потоке.
PS: вместо // do your line line поместите код, который использует захваченные ссылки r1 и r2, которые будут содержать данные или ноль, если результат не удался.