#azure #blazor
#azure #blazor
Вопрос:
Наше приложение Blazor (на стороне клиента) состоит из множества компонентов, которые одновременно существуют в пользовательском интерфейсе. Один из них должен выполнить несколько вызовов больших данных в Azure SQL. Этот компонент выполняет эти вызовы независимо от того, имеет ли он фокус пользовательского интерфейса или нет. Каждый из этих вызовов может занять до 3 секунд, чтобы вернуть свой результат, в течение которого пользовательский интерфейс перестает отвечать. Как мы можем поддерживать отзывчивый пользовательский интерфейс во время этих вызовов без использования Blazor на стороне сервера. Использование задачи.Запуск etc не помогает в однопоточной архитектуре. Использование загрузочных блесен также не является вариантом, поскольку это по-прежнему оставляет пользовательский интерфейс без ответа и может быть невидимым для пользователя. Есть ли какой-либо способ достичь этой цели в текущем Blazor 0.9.0?
Запуск последней версии предварительного просмотра Blazor (0.9.0-preview3-19154-02)
Комментарии:
1. Вы выполняете вызовы в Azure непосредственно с клиента? Я надеюсь, что нет, поскольку это означало бы передачу конфиденциальных строк подключения Azure и т.д. для клиента , что представляет собой серьезную угрозу безопасности! Я бы ожидал, что этот тип операции будет инициирован на клиенте, отправлен на сервер, а затем сервер отслеживает задачу Azure и обновляет клиент. SignalR был бы одним из способов сделать это или, возможно, запустить их как размещенные службы ?
2. HostedServices, как и планировалось, пытаются запустить другой поток, который невозможен в Blazor afaik. Метод SignalR может иметь больший потенциал для устранения этой проблемы.
Ответ №1:
Вы можете использовать Invoke
, я изменил counter
страницу примера, чтобы проиллюстрировать это, вам понадобится какой-то одноэлементный объект DI, чтобы избежать повторного запуска процесса.
Помните Blazor
, что это экспериментальный проект. Кроме того, этот ответ также является экспериментальным подходом.
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>
@functions {
int currentCount = 0;
void IncrementCount()
{
currentCount ;
}
protected override void OnInit()
{
Invoke(
//here your task.
async () =>
{
for(var i =0; i< 50; i )
{
await Task.Delay(1000);
currentCount ;
StateHasChanged();
System.Console.WriteLine("Still running ...");
}
});
}
}
Комментарии:
1. Спасибо за это, и да, я хорошо знаю, что он экспериментальный, начиная с 0.5 — попробую ваше предложение
2. Этот метод эффективно освобождает пользовательский интерфейс от длительных вызовов БД. Кажется, что интенсивная обработка процессора по-прежнему задерживает пользовательский интерфейс при вызове. Спасибо за вашу помощь @dani herrera
Ответ №2:
Если асинхронные вызовы не помогают, вы можете использовать browser workers, просто нужно реализовать некоторое взаимодействие js.
Комментарии:
1. Спасибо. Пару дней назад я просмотрел ваши образцы репозиториев web worker, но они делают не совсем то, что я хочу. Хорошая работа.
2. Да, у него была другая цель, но вы можете легко настроить ее под свои нужды.
3. Утром я еще раз подробно рассмотрю пример вашего рабочего браузера и попробую применить его. HostingService не выполняет задание, поскольку пытается создать другой поток. Другой вариант — использовать асинхронный вызов ajax для извлечения данных и ожидания ответа, но такое ощущение, что это нарушает модель
Ответ №3:
У меня был успех с Task().Start()
поместите свою работу в асинхронную задачу следующим образом:
async Task MyWork()
{
//sleep 10000
}
теперь, откуда бы вы ни хотели, чтобы эта работа блокировала вызов:
new Task( () => MyWork()).Start() );
Я использовал это только с сервером Blazor, поэтому не тестировал его на стороне клиента Blazor, который, как я слышал, может иметь разные результаты из-за его выполнения в одном потоке.
Комментарии:
1. На WebAssembly это не сработает, в лучшем случае это ничего не делает. На сервере Blazor используйте async / await и в очень редких случаях Task.Run().
2. В моем случае я использую интерфейс, который не допускает асинхронности / ожидания, поэтому выполнение задачи таким образом позволяет обойти это.
3. Тем не менее, Task.Run(), вероятно, имеет лучшие значения по умолчанию.
Ответ №4:
предложенный ответ не сработал, для меня я закончил тем, что использовал :
protected override void OnInitialized()
{
InvokeAsync(async () =>
{
myvar = await YourCodeHere();
StateHasChanged();
});
base.OnInitialized();
}
public async Task<MyVarType> YourCodeHere()
{
...
}
Объяснение: У меня есть класс с именем MyVarType, который я использую для отображения значений в компоненте Razor. У меня есть переменная myVar, созданная с помощью этого класса, и изначально она пуста. Компонент немедленно отобразит значения по умолчанию. После инициализации переменная также асинхронно назначается из инициализированного метода. Функция YourCodeHere может занять несколько секунд. Компонент Razor повторно выполняет при вызове StateHasChanged(), поэтому он отображает загруженные значения.