Более простой способ вызвать HttpClient (может быть, без задачи)? - PullRequest
1 голос
/ 02 мая 2019

Я работаю над приложением, которое будет использовать мой собственный REST endpoints (у меня есть проект onw WebApi).Теперь я пытаюсь создать приложение, которое будет работать на этой конечной точке.

Основываясь на этом руководстве по MSDN, я делаю что-то вроде этого:

Для тестирования я создаю приложение Console Core.Основной класс выглядит так:

class Program
{
    public static HttpDataService http = new HttpDataService("authorization token here");

    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        RunAsync().GetAwaiter().GetResult();
    }

    static async Task RunAsync()
    {
        var data = await http.Get("Default");
    }
}

Мой основной класс Http выглядит следующим образом:

public class HttpDataService
{
    public HttpDataService(string token)
    {
        this.HttpClient = new HttpClient();
        this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    }

    private HttpClient HttpClient { get; set; }

    public async Task<object> Get(string controller)
    {
        object data;
        HttpResponseMessage response = await this.HttpClient.GetAsync(UrlService.BuildEndpoint(controller));

        if (response.IsSuccessStatusCode)
        {
            data = await response.Content.ReadAsAsync<object>();
            return data;
        }
        else
        {
            throw new Exception(); //todo
        }
    }
}

Мне не понравился дополнительный шаг, который мне нужен, чтобы сделать метод для запуска задачи (RunAsync.GetAwaiter... в методе Main).

Есть ли более простой способ использования моих конечных точек?Может быть, какая-нибудь другая библиотека, которой не нужен дополнительный метод (таким образом, static Async Task Run)?Есть ли способ просто вызвать метод, как:

http.Get("Projects");

Без RunAsync() метод, который я пишу раньше?

PS.это консольное приложение работает нормально (я получаю значения из Default контроллера из моего проекта WebApi)

РЕДАКТИРОВАТЬ

Этот способ выглядит более удобным для пользователя:

static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        Task get = http.Get("default");

        RunAsync(get).GetAwaiter().GetResult();
    }

    static async Task RunAsync(Task endpoint)
    {
         await endpoint;
    }

но как получить это от endpoint?

Ответы [ 3 ]

2 голосов
/ 02 мая 2019

Есть 2 проблемы с вашим кодом. Во-первых, ваш метод RunAsync возвращает Task, а метод HttpDataService.Get возвращает Task<object>. Чтобы получить результат от конечной точки, RunAsync должен вернуть Task<object>. Когда вы дождетесь этой задачи, вы получите объект с вашим результатом.

Для .GetAwaiter().GetResult() есть 2 варианта. Во-первых, вы можете создать static async Task MainAsync, где вы запустите весь свой код и вызовете этот метод из несинхронизированного Main -метода, вызвав MainAsync().GetAwaiter().GetResult(). До C # 7.1 это был путь.

static void Main(string[] args)
{
    MainAsync(args).GetAwaiter().GetResult();
}

static async Task MainAsync(string[] args)
{
    // Run your async code here
}

Если вы используете C # 7.1, вы можете сделать Main -метод асинхронным (static async Task Main(string[] args)), и оттуда вы можете напрямую вызвать свой асинхронный код.

static async Task Main(string[] args)
{
    // Run your async code here
}
1 голос
/ 02 мая 2019

Вы должны сделать Main асинхронным.

note : работает только с современным c #

static async Task Main(string[] args)
{
    var result = await http.Get("default");
}
1 голос
/ 02 мая 2019

Вы можете использовать вспомогательный класс

public static class AsyncHelper  
{
    private static readonly TaskFactory _taskFactory = new
        TaskFactory(CancellationToken.None,
                    TaskCreationOptions.None,
                    TaskContinuationOptions.None,
                    TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();

    public static void RunSync(Func<Task> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();
}

, позволяющий вам сделать это:

static async Task RunAsync(Task endpoint) {
   AsyncHelper.RunSync(() => endpoint());  
}

PS.посмотрите здесь Ms AsyncHelper и здесь C # Async Tips & Tricks

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...