оператор ожидания выдачи проблемы при использовании с лямбда - PullRequest
0 голосов
/ 23 июня 2018

У меня есть 2 Entity, и я хочу скопировать некоторые данные из Second Entity в First Entity, и после этого я хочу вернуть простую строку с надписью Success. Я использую Polly для выполнения http-запроса. Я планирую получить данные в json а затем преобразовать его в мою модель Entity и выполнить манипуляции, которые я могу сделать, но вызывая обе задачи, которые возвращают разные типы (могут быть незначительно отличающиеся модели данных), что приводит к некоторой ошибке. Я не так хорош в подходе многопоточности.

public interface IMyRepository 
{
    string ValidateData(MyData myData);
}


public class MyRepository :IMyRepository 
{        private  readonly RetryPolicy<HttpResponseMessage> _httpRequestPolicy;

    public MyRepository()
    {

        _httpRequestPolicy = Policy.HandleResult<HttpResponseMessage>(
             r => r.StatusCode == HttpStatusCode.InternalServerError)
         .WaitAndRetryAsync(3,
             retryAttempt => TimeSpan.FromSeconds(retryAttempt), (exception, timeSpan, retryCount, context1) =>
             {
                 var msg = $"Retry {retryCount} implemented with Pollys RetryPolicy " +
                 $"of {context1.PolicyKey} " +
                 $"at {context1.ExecutionKey}, " +
                 $"due to: {exception}.";


             });
    }

    public  string  ValidateData(MyData MyData)
    {            
       var MyDataOne= Task<MyData>.Factory.StartNew(() => await  MyRepository.getProfileOne());
       var MyDataTwo= Task<MyData>.Factory.StartNew(() => await  MyRepository.getProfileTwo());
       //Update some property of MyDataOne on basis of MyDataTwo and return true or fasle in variable **result**
        return result;
    }

    public static async Task<InsuranceCompanyData> getCusomerProfile()
    {
        var httpClient = GetHttpClient();
        string requestEndpoint = "numbers/Get";

        HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => httpClient.GetAsync(requestEndpoint));

        IEnumerable<int> numbers = await httpResponse.Content.ReadAsAsync<IEnumerable<int>>();
        return  new InsuranceCompanyData();
    }
    private  static HttpClient GetHttpClient()
    {
        var httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri(@"http://localhost:2351/api/");
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        return httpClient;
    }
}

public static async  Task<MyData> getProfileOne()
{
    var httpClient = GetHttpClient();
    string requestEndpoint = "/numbers/Get1";

    HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => httpClient.GetAsync(requestEndpoint));

   // IEnumerable<string> data1= await httpResponse.Content.ReadAsAsync<IEnumerable<string>>();
    return  new MyData();
}

public static async  Task<MyData> getProfileTwo()
{
    var httpClient = GetHttpClient();
    string requestEndpoint = "/numbers/Get2";

    HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => httpClient.GetAsync(requestEndpoint));

  //  IEnumerable<string> data2= await httpResponse.Content.ReadAsAsync<IEnumerable<string>>();
    return  new MyyData();
}

private  static HttpClient GetHttpClient()
{
    var httpClient = new HttpClient();
    httpClient.BaseAddress = new Uri(@"http://localhost:2351/api/");
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    return httpClient;
}

Я получаю эти ошибки:

Оператор 'await' может использоваться только внутри асинхронного лямбда-выражения. Попробуйте пометить это лямбда-выражение модификатором async.

И

Ссылка на объект требуется для нестатического поля, метода или свойства 'MyRepository._httpRequestPolicy'

Ответы [ 2 ]

0 голосов
/ 23 июня 2018

Почему бы вам не изменить ValidateData подпись и добавить async ключевое слово в метод?

    public async Task<string> ValidateDataAsync(MyData MyData)
    {            
       var task1 = Task<MyData>.Factory.StartNew(() => MyRepository.getProfileOne());
       var task2 = Task<MyData>.Factory.StartNew(() => MyRepository.getProfileTwo());

       await Task.WhenAll(task1, task2)       

       //Update some property of MyDataOne on basis of MyDataTwo and return true or fasle in variable **result**
        return result;
    }

Как сказал @Camilo Terevinto, лучше использовать Task.Run вместо TaskFactory.StartNew.

Task.Run vs Task.Factory.StartNew

0 голосов
/ 23 июня 2018

Вместо использования Task.Factory.StartNew, который не рекомендуется и не поддерживает асинхронные лямбды (которые вам здесь даже не нужны), используйте Task.Run:

var profileOneTask = Task.Run(() => getProfileOne());
var profileTwoTask = Task.Run(() => getProfileTwo());

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

Для второй проблемы вы объявили _httpRequestPolicy как член экземпляра, когда вы должны были объявить его как статический член, чтобы его можно было использовать без экземпляра.Как уже говорилось в комментариях, вы можете просто создать getProfileOne и getProfileTwo методы экземпляра.

...