2016-03-16 2 views
1

У меня есть интерфейс, который доставляет мне определенный путь. В одной из моих реализаций мне нужно использовать async, но я не понял, как получить результат асинхронного метода в синхронный метод. Вот пример кода:Интерфейс, где одна из реализаций должна быть асинхронной

Интерфейс:

public interface IFilePath 
{ 
    string GetAsset(); 
} 

Проблемной реализация:

public class FilePath : IFilePath 
{ 
    public string GetAsset() 
    { 
     return GetAssetAssync(); 
    } 

    private async Task<string> GetAssetAssync() 
    { 
     StorageFolder assetsFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(@"Assets").AsTask().ConfigureAwait(false); 
     return assetsFolder.Path; 
    } 
} 

Только для этого мне нужно выполнения вызова асинхронного. Все остальные не нужны. Поэтому я не могу использовать public Task<string> GetAsset() или могу ли я как-нибудь?

+2

Каков ваш вопрос? Либо добавьте обе подписи в интерфейсе, либо создайте отдельную библиотеку только для асинхронного доступа. [Конечно, не вызывайте '... Async(). Результат из синхронного кода] (http://stackoverflow.com/questions/22628087/calling-async-method-synchronously) (взаимоблокировки, обработка исключений). – CodeCaster

+0

'.Result'. Однако, в общем, вам лучше предлагать только асинхронную версию и оставлять ее вызывающим абонентам для вызова '.Result' сами, если они настаивают на синхронной версии, а не на ее обертку самостоятельно. Это побуждает других абонентов использовать асинхронную версию, вместо того, чтобы легко и быстро записывать (неэффективно завернутый) код блокировки. –

+0

Или вы могли бы просто сделать GetAssetAssync(). ConfigureAwait (false); 'который не будет deadlock –

ответ

6

Метод возврата задачи указывает, что реализация может быть быть асинхронной. Таким образом, лучший подход, чтобы обновить интерфейс, чтобы асинхронные реализации:

public interface IFilePath 
{ 
    Task<string> GetAssetAsync(); 
} 

Я попытался бы сделать другие реализации асинхронной (файл I/O является естественным асинхронной операцией), но если у вас есть действительно синхронные реализации (например, чтение из архива в памяти или что-то), то вы можете обернуть свой результат в Task.FromResult:

class SynchronousFilePath: IFilePath 
{ 
    public string GetAsset(); // natural synchronous implementation 

    public Task<string> GetAssetAsync() 
    { 
    return Task.FromResult(GetAsset()); 
    } 
} 
+1

В качестве ответа на этот вопрос: Если вы используете Task.FromResult в реализации, я бы задокументировал, что он заблокирует вызывающий поток для ваших дорогостоящих разработчиков настольных приложений, которые ожидают, что смогут дождаться этого и сохранить разблокировку их пользовательского интерфейса. чтобы обнаружить, что они блокируются из детали реализации .FromResult. – davidallyoung

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