Аннотация:
В этой статье создается новый шаблон асинхронного программирования, предлагаемый к использованию вместо рекомендуемого Microsoft шаблона асинхронного программирования основанного на событиях.
Re: Шаблон разработки асинхронного программирования
ПЭA>Авторы: ПЭA> Павлов Эдуард aka Ed.ward
ПЭA>Аннотация: ПЭA>В этой статье создается новый шаблон асинхронного программирования, предлагаемый к использованию вместо рекомендуемого Microsoft шаблона асинхронного программирования основанного на событиях.
Интересная статья, открыл для себя новые классы.
Наверное глупый вопрос, но все же. Где найти интерфейс IAsyncOperation и класс AsyncOperation<TResult>? В МСДНе смотрел — нет их (МСДН от 2008 студии). Или имеется ввиду, что так будет называться разрабатываемый автором класс, который будет использоваться в новом шаблоне?
Re[2]: Шаблон разработки асинхронного программирования
Здравствуйте, sada12, Вы писали:
S>Интересная статья, открыл для себя новые классы. S>Наверное глупый вопрос, но все же. Где найти интерфейс IAsyncOperation и класс AsyncOperation<TResult>? В МСДНе смотрел — нет их (МСДН от 2008 студии). Или имеется ввиду, что так будет называться разрабатываемый автором класс, который будет использоваться в новом шаблоне?
Интерфейс IAsyncOperation и класс AsyncOperation<TResult> являются частью реализации этого шаблона, их создание и есть цель работы.
Ссылка на исходники, видимо, будет доступна вместе с полной версией статьи, признаться, не знаю тонкостей публикации статей на сайте.
Ed.ward
Re: Шаблон разработки асинхронного программирования
ПЭA>>...И если от объявления делегата можно избавиться, воспользовавшись делегатом Action<T1, T2>, появившимся в .NET 3.5...
Q>От объявления делегата нужно избавиться, воспользовавшись делегатом EventHandler<TEventArgs>, появившемся ещё в .NET 2.0.
Да, действительно, спасибо.
Я про него забыл, потому что сам пользовался своим делегатом EventHandler<TSender, TEventArgs>
Ed.ward
Re: Шаблон разработки асинхронного программирования
однако в прилагаемых исходниках (IAsyncOperation.cs):
public interface IAsyncOperation< TResult, TIntermediateResult > : IAsyncOperation< TResult >
{
/// <summary>
/// Получает промежуточный результат операции.
/// </summary>
TIntermediateResult IntermediateResult { get; }
/// <summary>
/// Сигнализирует о необходимости прервать выполнение операции после данной итерации.
/// </summary>bool BreakExecution{ set; }
}
get-тера на свойство BreakExecution нет.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Шаблон разработки асинхронного программирования
ПЭA>Авторы: ПЭA> Павлов Эдуард aka Ed.ward
ПЭA>Аннотация: ПЭA>В этой статье создается новый шаблон асинхронного программирования, предлагаемый к использованию вместо рекомендуемого Microsoft шаблона асинхронного программирования основанного на событиях.
А мне понравилась (по сравнению с другими моделями) не описанная в статье модель с использованием AsyncEnumerator...
Хорошо уживается с IAsyncResult (более высокоуровневая), и не нужно табуны методов/делегатов писать.
Пишу с её использованием серверную программулину (правда, отладку многопоточной проги эта модель ничуть не упрощает))).
Re: Шаблон разработки асинхронного программирования
Здравствуйте, Павлов Эдуард aka Ed.ward, Вы писали:
В методе GetResult(out Exception) закрывается и обнуляется экземпляр ManualResetEvent...
Я считаю, что закрывать его можно только в том случае, когда есть абсолютная уверенность, что кроме метода GetResult никто не обращался к свойству AsyncWaitHandle, иначе другие потребители имеют шансы схлопотать ObjectDisposedException, если обратятся к методу WaitOne после закрытия ивента.
Еще один момент: не должно быть сценариев, при которых свойство WaitHandle возвращает разные экземпляры ManualResetEvent, потому обнулять поле _waitHandle тоже нужно только в полной уверенности, что к свойству AsyncWaitHandle никто не обращался.
Потому, если освободить ивент все-же хочется (а лучше бы его освобождать, хотя бы в тех случаях, когда можно), то предлагаю под ивент завести два поля. Одно из них будет обслуживать свойство для внутренних нужд (тот же GetResult), другое — для внешних. И освобождать ивент только в случае, когда поле под внешние нужды пусто (проверять в критической секции). Или завести флаг, было ли обращение к внешнему свойству (устанавливать и проверять тоже в критической секции).
А вообще шаблон понравился.
Re: Шаблон разработки асинхронного программирования
Еще мне не нравится тот факт, что метод Cancel ведет себя так, будто он синхронно завершил вычисления (ставит в положение Set _waitHandle и вызывает событие OperationComplete), хотя фактически вычисления могут в это время продолжать крутиться, особенно если свойство IsCanceled опрашивается редко.
Фактически это дезинформация, ну и потом, в событии OperationComplete может быть вызван метод GetResult еще до того, как поток вычислений опросит флаг IsCanceled. Или даже поток вычислений может столкнуться с исключением, и вызвать SetAsCompleted с этим исключением, однако это исключение не увидит никто, если GetResult уже отработал.
По поводу отмены операции отмены:
Вероятны сценарии, когда потребитель заказал отмену (вызвал Cancel), но до очередного опроса IsCanceled вычисляющему потоку стало ясно, что операция успешно завершена (допустим, мы только что закрыли транзакцию, или изменили какое-то глобальное состояние). В этом случае, потребителю нужно отрапортовать о том, что операция таки выполнена, вопреки его пожеланию об отмене.
Я считаю, что метод Cancel должен только лишь устанавливать флаг о желании пользователя отменить операцию и возвращать управление (и не делать проверку на повторный вызов), а все события должны срабатывать после фактического окончания работы (и WaitHandle тоже). Тогда потребителю можно будет сообщить об успехе выполнения операции, даже если был вызван Cancel.