Я использую асинхронные операции в моем клиенте WinForms с самого начала, но только для некоторых операций. Когда завершается ExecuteReader
или ExecuteNonQuery
, делегат обратного вызова срабатывает, и все работает нормально.
У меня в основном есть две проблемы:
1) Какая лучшая структура для решения этой проблемы в реальной системе? Все примеры, которые я видел, - это примеры игрушек, в которых форма обрабатывает завершение операции, а затем открывает datareader на EndExecuteReader
. Конечно, это означает, что форма более тесно связана с базой данных, чем обычно. И, конечно, форма всегда легко может называть .Invoke
сама по себе. Я установил все мои асинхронные объекты для наследования из класса AsyncCtrlBlock<T>
и получил форму и все делегаты обратного вызова, предоставленные конструктору асинхронных объектов в моем DAL.
2) Я собираюсь повторно посетить часть программы, которая в настоящее время не является асинхронной. Он делает два вызова подряд. Когда первое будет завершено, часть модели может быть заполнена. Когда вторая будет завершена, оставшаяся часть модели может быть завершена, но только если первая часть уже выполнена. Каков наилучший способ структурирования этого? Было бы здорово, если первое чтение может быть выполнено, и обработка, связанная с первым чтением, будет продолжена, пока вторая будет запущена, но я не хочу, чтобы обработка второго чтения начиналась, пока я не знаю, что обработка первые прочитанные данные завершены.
Если вы находитесь на .Net 4, это будет идеальное приложение TPL! Вы можете включить код в такие задачи:
TaskScheduler uiScheduler = GetUISheduller();
SqlCommand command1 = CreateCommand1();
Task<SqlDataReader> query1 = Task<SqlDataReader>.Factory.FromAsync(command1.BeginExecuteReader, command1.EndExecuteReader, null);
query1.ContinueWith(t => PopulateGrid1(t.Result), uiScheduler);
SqlCommand command2 = CreateCommand2();
query1.ContinueWith(t => Task<SqlDataReader>.Factory.FromAsync(command2.BeginExecuteReader, command2.EndExecuteReader, null)
.ContinueWith(t => PopulateGrid2(t.Result), uiScheduler);
относительно 2)
сделать первую фазу вашей модели, заполняющей асинхронную. у вас будет что-то вроде этого
FisrtCall();
AsyncResult arPh1 = BeginPhaseOne(); //use results from first call
SecondCall();
EndPhaseOne(arPh1); //wait until phase one is finished
PhaseTwo(); //proceed to phase two