2015-07-19 4 views
2

При работе с API данных, использующих async rest calls (я использую RestSharp.Portable), каков наилучший способ обработки возвращаемых значений? Поскольку функция async может возвращать только задачу или задачу ... но у вызывающего нет возможности вернуться к возвращаемому значению ... как API вернет данные обратно вызывающему абоненту? Глобальные свойства?Как обрабатывать возвращаемые значения в async-функции

Из того, что я прочитал до сих пор, кажется, что функции обратного вызова являются единственным способом взаимодействия с данными ответа?

Возьмем, например, следующий метод; раньше я не использовал библиотеку асинхронной Rest и был в состоянии вернуть значение, но после преобразования его использовать RestSharp.Portable, я не вижу способ вернуть значение:

public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType) 
    { 
     TaskCompletionSource<EntityResourceDescriptor> tcs = new TaskCompletionSource<EntityResourceDescriptor>(); 
     var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}"); 
     AddDomainAndProject(req); 
     req.AddParameter("entityType", entityType, ParameterType.UrlSegment); 
     client.ExecuteAsync<EntityResourceDescriptor>(req, (res) => 
      { 
       if (res.ResponseStatus == ResponseStatus.Error) 
       { 
        tcs.TrySetException(res.ErrorException); 
       } 
       else 
       { 
        tcs.SetResult(res.Data); 
       } 
      } 
     ); 
     return tcs.Task; 
    } 

Вот все, что я могу сделать, это вернуть Task но у вызывающего абонента все еще нет возможности добраться до данных ответа или я пропущу что-то очевидное? Может ли абонент подписаться на событие, которое запускается в Task.Completed и т. Д.?

Я очень нечеткий по этой концепции асинхронный. Есть ли примеры написания переносимых API данных?

+0

Я не понимаю проблему. Вы задаете результат задачи. Эти данные будут возвращены вызывающему, когда задача будет завершена. –

+0

Не совсем, потому что метод выходит сразу после отправки client.ExecuteAsync. В то время как tcs.Task не обеспечивает прямой способ взаимодействия со значением. Когда я добавляю ключевое слово 'wait' (чтобы завершить выполнение метода до выхода), я начал получать ошибки компилятора, которые были специфичны для RestSharp.Portable exe и на самом деле не имели для меня никакого смысла. Я рассмотрю статью, предложенную @sstan, и посмотрим, будут ли ошибки иметь смысл или нет. Вероятно, у меня есть что-то очевидное в моей реализации. Спасибо, что ответили! – Robert

ответ

2

Я думаю, вам действительно нужно сделать шаг назад и прочитать о том, как использовать ключевые слова async и await. Помимо всего прочего, вам нужно будет понять некоторые магии компилятора, которые происходят за кулисами при кодировании методов async.

Это хорошее место для начала: Asynchronous Programming with Async and Await.

Больше на ваш вопрос, раздел Return Types and Parameters имеет это сказать:

Вы указываете Task<TResult> в качестве возвращаемого типа, если метод содержит Return (Visual Basic) или return (C#) утверждение, что указывает операнд типа TResult.

Затем он приводит следующий пример кода:

// Signature specifies Task<TResult> 
async Task<int> TaskOfTResult_MethodAsync() 
{ 
    int hours; 
    // . . . 
    // Return statement specifies an integer result. 
    return hours; 
} 

Обратите внимание, как, несмотря на метод обратного типа Task<int>, тем return оператор просто возвращает int, а не Task<int>. Это в основном потому, что есть некоторая магия компилятора, которая делает это законным только в методах async.

Не желая попасть во все детали, вы также должны знать, что абонент метода async обычно ожидается, сделать это, используя await ключевое слово, которое знает, как бороться с возвращаемые значения Task или Task<TResult> и автоматически разворачивает фактическое ожидаемое возвращаемое значение для вас прозрачным образом (больше магии компилятора за кулисами).

Таким образом, для приведенного выше примера, вот один из способов назвать его:

int intValue = await TaskOfTResult_MethodAsync(); // Task<int> is automatically unwrapped to an int by the await keyword when the async method completes. 

Или, если вы хотите, чтобы запустить метод асинхронного, выполнять другую работу в то же время, а затем ждать асинхронного метод, чтобы закончить, это можно сделать так:

Task<int> t = TaskOfTResult_MethodAsync(); 
// perform other work here 
int intValue = await t; // wait for TaskOfTResult_MethodAsync to complete before continuing. 

Надеется, что это дает вам общее представление о том, как передавать значения обратно из метода асинхронного.

Для вашего конкретного примера я не знаком с RestSharp (никогда не использовал его). Но из того, что мало читаю, я думаю, вы захотите использовать client.ExecuteTaskAsync<T>(request) вместо client.ExecuteAsync<T>(request, callback), чтобы лучше поместиться в модели async-await.

Я думаю, что ваш метод вместо этого выглядеть примерно так:

public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType) 
{ 
    var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}"); 
    AddDomainAndProject(req); 
    req.AddParameter("entityType", entityType, ParameterType.UrlSegment); 
    var res = await client.ExecuteTaskAsync<EntityResourceDescriptor>(req); 

    if (res.ResponseStatus == ResponseStatus.Error) 
    { 
     throw new Exception("rethrowing", res.ErrorException); 
    } 
    else 
    { 
     return res.Data; 
    } 
} 

Ваш вызывающий код будет выглядеть следующим образом:

EntityResourceDescriptor erd = await GetEntityDescriptor("entityType"); 

Я надеюсь, что вам удастся получить эту работу. Но опять же, обязательно прочитайте документацию о стиле программирования async-await. Это очень аккуратно, когда вы завертываете магию компилятора, которая выполняется для вас. Но так легко потеряться, если вы не нашли времени, чтобы действительно понять, как это работает.

+0

Спасибо за ссылку на эту статью. Я попробую ваше предложение и посмотрю, смогу ли я все понять. – Robert

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