Blazor Server, запускающий задачу, останавливает приложение

У меня есть приложение Blazor Server, которое вызывает несколько API. Все работает нормально, но я пытаюсь завернуть эти звонки в Tasks. Как только мой код доходит до вызова, все просто останавливается. Я уверен, что делаю что-то глупое, но никакие поиски в Google не находят мне решения. Вызов исходит из сетки Syncfusion при выборе строки. Вот мой минимальный воспроизводимый код:

public static IEnumerable<Quotation> customerQuotations = Array.Empty<Quotation>();

public async Task CustomerRowSelectHandler(RowSelectEventArgs<Customer> args)
{
    GetCustomerQuotes(args.Data.customerId);
}

static async void GetCustomerQuotes(int customerId)
    {
        string url = string.Format(@"https://my.server.dns/quotations/customer/{0}", customerId);
        var task = GetJsonString(url);
        task.Wait();
        customerQuotations = (IEnumerable<Quotation>)JsonConvert.DeserializeObject<Quotation>(task.Result);
    }

private static async Task<string> GetJsonString(string url)
    {
        var TCS = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
        var myClient = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
        HttpResponseMessage response = await myClient.GetAsync(url);
        string streamResponse = await response.Content.ReadAsStringAsync();
        TCS.SetResult(streamResponse);
        return await TCS.Task;
    }

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

Спасибо в ожидании любой предложенной помощи.

Всегда избегайте async void

H H 02.02.2023 11:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Основная проблема, это Task.Wait(). Это может зайти в тупик.

public async Task CustomerRowSelectHandler(RowSelectEventArgs<Customer> args)
{
    //GetCustomerQuotes(args.Data.customerId);
    await GetCustomerQuotes(args.Data.customerId);
}

//static async void GetCustomerQuotes(int customerId)
    async Task GetCustomerQuotes(int customerId)
    {
        string url = string.Format(@"https://my.server.dns/quotations/customer/{0}", customerId);
        var task = GetJsonString(url);
        // task.Wait();
        await task;
        customerQuotations = (IEnumerable<Quotation>)JsonConvert.DeserializeObject<Quotation>(task.Result);
    }

и конечно

var task = GetJsonString(url);
await task;
   ... (task.Result)

может (должен) стать

string result = await GetJsonString(url);
    ...  (result)

И когда вам не нужен объект ответа (для кода состояния и т. д.), все это можно сделать в 1 строке:

customerQuotations = await myClient.GetFromJsonAsync<Quotation[]>(url); 

Похоже, вы слишком усложняете асинхронное кодирование в вызове API. Зачем вам нужно построить TaskCompletionSource? У вас могут быть причины, но они не очевидны в коде вашего вопроса.

Почему бы не что-то вроде этого:

    public async Task CustomerRowSelectHandler(...)
    {
        await GetCustomerQuotes(...);
    }

    private async ValueTask GetCustomerQuotes(...)
    {
        string url = string.Format(@"....");
        var http = new HttpClient(...);
        HttpResponseMessage response = await http.GetAsync(url);
        if (response.IsSuccessStatusCode)
            customerQuotations = await response.Content.ReadFromJsonAsync<IEnumerable<Quotation>>() ?? Enumerable.Empty<Quotation>(); ;
       // handle errors
    }

Или даже это, но вы теряете перехват ошибок.

customerQuotations = await http.GetFromJsonAsync<IEnumerable<Quotation>>(url);

Вам также следует рассмотреть возможность использования IHttpClientFactory для управления экземплярами http.

MrC - большое спасибо, что нашли время, чтобы помочь мне. Я не разработчик, просто парень, пытающийся выжить, поэтому, когда люди с большим опытом берутся за эту проблему, это действительно много значит. Еще раз спасибо.

SkinnyPete63 03.02.2023 08:40

Просто для полноты, TaskCompletionSource взят из другой статьи, за которой я следил. Этого больше нет, еще одна причина поблагодарить MrC! Пытаюсь реализовать IHttpClientFactory и получаю ошибку, которую я разместил здесь: stackoverflow.com/questions/75334007/…

SkinnyPete63 03.02.2023 11:15

TaskCompletionSource предназначен для более специализированных и сложных ситуаций. Здесь совершенно ненужно. Видишь, ты разобрался со своей проблемой.

MrC aka Shaun Curtis 03.02.2023 21:16

Каждый день - учебный день! Еще раз спасибо за вашу помощь.

SkinnyPete63 04.02.2023 04:43

Другие вопросы по теме