2013-06-07 4 views
2

Есть ли рекомендуемая рекомендация/руководство по экспорту синхронных и асинхронных версий API в библиотеке классов? Например, если у меня есть следующие 2 методы, определенные в библиотеке классов:Предоставление синхронных и асинхронных версий API в библиотечном коде

public Task<string> GetSomeDataAsync() 
    { 
     //typically an IO operation that would be awaited on, simplified to return a Task for illustration 
     return Task<string>.Factory.StartNew(() => "foo"); 
    } 

    public string GetSomeDataSync() 
    { 
     var task = GetSomeDataAsync(); 
     task.ConfigureAwait(continueOnCapturedContext: false); 
     return task.Result; 
    } 

выше может быть размещен в клиентском приложении Winform/WPF/консоли/ASP.NET. Безопасно ли для клиента использовать синхронную версию, выше которой используется task.Result, учитывая, что задача сконфигурирована так, чтобы не фиксировать какой-либо контекст синхронизации, чтобы избежать возможных взаимоблокировок.

ответ

-1

Существует 3 «основных» варианта для асинхронных шаблонов, которые одобрены MS. Я бы рекомендовал вам выбрать один из шаблонов и придерживаться его ... Похоже, вы уже направляетесь к «Асинхронному шаблону на основе задач», поэтому у вас будет очень мало модов, чтобы соответствовать шаблону , Это позволяет создавать ваши методы таким образом, чтобы они были едиными и интуитивно понятными для других потребителей ... Они будут знать шаблон из библиотек .NET, созданных MS. Смотрите это для деталей:

Обзор: http://msdn.microsoft.com/en-us/library/jj152938.aspx

Задача Асинхронный шаблон: http://msdn.microsoft.com/en-us/library/hh873175.aspx

Пример ваших методов с помощью Task Asynchronous Pattern с поддержкой отмены лексем:

public Task<string> GetSomeDataAsync(CancellationToken cancellationToken = null) 
{ 
    return Task<string>.Factory.StartNew(() => "foo", cancellationToken); 
} 

// NOTE: no need to append Sync to the method name, redundant. 
public string GetSomeData() 
{ 
    var task = GetSomeDataAsync(); 
    task.ConfigureAwait(continueOnCapturedContext: false); 
    return task.Result; 
} 
+0

Я не думаю, что это на самом деле отвечает на вопрос, вы не обращаетесь к двум методам. – svick

+0

Хорошо, я добавлю немного больше. – Haney

3

Я думаю, что лучший совет по этому поводу состоит из двух статей Стивена Туба:

Второй является более актуальной для вас. Короче говоря, в нем говорится, что вы не должны этого делать. Если вызывающий ваш метод решает подождать синхронно, он все равно может сделать этот выбор, и он находится в лучшем положении, чем вы, чтобы сделать это (потому что он знает окружающую среду, поэтому он должен знать, являются ли проблемы взаимоблокировки, например).

Вышеупомянутый может быть размещен в клиентском приложении Winform/WPF/Console/ASP.NET. Безопасно ли для клиента использовать синхронную версию, выше которой используется task.Result, учитывая, что задача сконфигурирована так, чтобы не фиксировать какой-либо контекст синхронизации, чтобы избежать возможных взаимоблокировок.

Вы ошибаетесь в этом. ConfigureAwait() не изменяет Task любым способом (тем более, что Task уже выполняет в этой точке). Все, что он делает, это вернуть ConfiguredTaskAwaitable, а если вы await, то он не возобновится в захваченном контексте.

Это означает, что ваш метод будет по-прежнему заторможен.

+0

Это отличная рекомендация, вторая ссылка была особенно полезна! Для приложений ASP.NET это означает, что ваши веб-страницы будут асинхронны? –

+0

@AbhijeetPatel Да, если это имеет смысл для вас. Я не думаю, что все должно быть асинхронным, особенно если это означает переписывание существующего кода. – svick

+0

@svik: Проблема в том, что клиент в конечном итоге вызывает службу HTTP REST с использованием API HttpClient. Единственный способ получить данные - использовать методы GetAsync в API HttpClient (синхронной версии нет). Это (как мы знаем) делает всех вызывающих абонентов выше по течению async. Поэтому мой первоначальный вопрос о предоставлении «синхронизации» версии которого по существу формирует блокирующий вызов через task.Wait() или task.Result. Я думал, что если контекст синхронизации не будет захвачен, вы не столкнетесь с проблемами потоков, но ваш поток клиентов действительно будет заблокирован. Мысли? –

Смежные вопросы