Просто дикая догадка, может ли это быть из-за того, что вы определяете Loader
после , когда используете его?
Взгляните на этот пример:
вызовет событие Completed и выведет «done» в Debug Output, как только оба сервиса вернутся. Главное, чтобы ожидание AutoResetEvents происходило в фоновом потоке.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Completed += (s, a) => { Debug.WriteLine("done"); };
wrk.DoWork += (s, a) =>
{
Start();
};
wrk.RunWorkerAsync();
}
public event EventHandler Completed;
private void Start()
{
auto1.WaitOne();
auto2.WaitOne();
Completed(this, EventArgs.Empty);
}
public AutoResetEvent auto1 = new AutoResetEvent(false);
public AutoResetEvent auto2 = new AutoResetEvent(false);
BackgroundWorker wrk = new BackgroundWorker();
private void Button_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client clien = new SilverlightAsyncTest.ServiceReference1.Service1Client();
clien.DoWorkCompleted += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs>(clien_DoWorkCompleted);
clien.DoWork2Completed += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs>(clien_DoWork2Completed);
clien.DoWorkAsync();
clien.DoWork2Async();
}
void clien_DoWork2Completed(object sender, SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs e)
{
Debug.WriteLine("2");
auto1.Set();
}
void clien_DoWorkCompleted(object sender, SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs e)
{
Debug.WriteLine("1");
auto2.Set();
}
}
Это можно сделать с помощью WaitHandle в IAsyncResult, возвращаемом каждым асинхронным методом.
Код прост. В Silverlight я просто делаю 10 сервисных вызовов, которые добавляют элемент в ListBox. Я подожду завершения всех сервисных вызовов, чтобы добавить еще одно сообщение в список (это должно выполняться в другом потоке, чтобы избежать блокировки пользовательского интерфейса). Также обратите внимание, что добавление элементов в список должно выполняться через Диспетчер, поскольку они изменяют пользовательский интерфейс. Существует множество ламд, но им легко следовать.
public MainPage()
{
InitializeComponent();
var results = new ObservableCollection<string>();
var asyncResults = new List<IAsyncResult>();
resultsList.ItemsSource = results;
var service = new Service1Client() as Service1;
1.To(10).Do(i=>
asyncResults.Add(service.BeginDoWork(ar =>
Dispatcher.BeginInvoke(() => results.Add(String.Format("Call {0} finished: {1}", i, service.EndDoWork(ar)))),
null))
);
new Thread(()=>
{
asyncResults.ForEach(a => a.AsyncWaitHandle.WaitOne());
Dispatcher.BeginInvoke(() => results.Add("Everything finished"));
}).Start();
}
Просто чтобы помочь с тестированием, это сервис
public class Service1
{
private const int maxMilliSecs = 500;
private const int minMillisSecs = 100;
[OperationContract]
public int DoWork()
{
int millisSecsToWait = new Random().Next(maxMilliSecs - minMillisSecs) + minMillisSecs;
Thread.Sleep(millisSecsToWait);
return millisSecsToWait;
}
}