Фоновая служба Blazor не останавливается/отменяется должным образом ⇐ C#
Фоновая служба Blazor не останавливается/отменяется должным образом
Я создаю простое приложение, которое подсчитывает слова в файлах. Я выбрал blazor, потому что хотел опробовать его и потому что поддерживать отзывчивость интерфейса относительно легко.
У меня есть сервис для выполнения реальной работы. В своем пользовательском интерфейсе я вызываю службу следующим образом:
private async void InputFileChanged(InputFileChangeEventArgs e) { если (Сервис.Работает) { возвращаться; } IReadOnlyList files = e.GetMultipleFiles(); пытаться { cancelTokenSource = новый CancellationTokenSource (); wordCounts = ждут Service.GetWordCounts(files, cancelTokenSource.Token); ПрогрессПроцент = 100; } поймать (OperationCanceledException ex) { Сервис.Стоп(); wordCounts = ноль; ПрогрессПроцент = 0; } СостояниеИзменено(); } Теперь вы можете заметить Service.Stop(); внутри блока catch. Именно это меня и не радует.
По сути, при отмене процесса обслуживания служба выдает исключение, как это обычно бывает с токенами отмены. При выдаче исключения я уже вызываю этот метод Stop(). Однако служба, похоже, никогда не достигает блоков кода, содержащих throw, даже несмотря на то, что она генерирует исключение. Я проверил с помощью точек останова, и он никогда не прерывается при вызовах внутри службы.
Есть идеи о том, что я делаю неправильно или что я могу улучшить, чтобы не вызывать этот метод Stop() вне службы?
FileCounterService:
с использованием Microsoft.AspNetCore.Components.Forms; использование System.ComponentModel; пространство имен FileWordCounter.Service { общедоступный класс FileCounterService { public bool Running { get; частный набор; } публичное событие ProgressChangedEventHandler? ПрогрессИзменен; частный StreamReader? читатель = ноль; частный длинный totalBytes; частный длинный ProgressedBytes; public async Task GetWordCounts( файлы IEnumerable, Токен отмены (Token отмены) { //инициализируем сервис Запуск = правда; Dictionary wordCounts = новый Dictionary(); //сбрасываем значения прогресса totalBytes = files.Sum(x => x.Size); прогресседбайтс = 0; //прокручиваем каждый файл foreach (файл IBMrowserFile в файлах) { //максимальный размер файла 1 ГиБ должен охватывать большинство файлов клиентов длинный maxFileSize = 1024L * 1024 * 1024 * 1024; пытаться { читатель = новый StreamReader(file.OpenReadStream(maxFileSize, cancelToken)); } поймать (OperationCanceledException ex) { Останавливаться(); бросить бывшего; } нить? линия = ждут читателя.ReadLineAsync(); в то время как (строка != ноль) { если (строка == "") { линия = ждут читателя.ReadLineAsync(); продолжать; } строка[] слова = line.Split(' '); foreach (строковое слово в словах) { если (string.IsNullOrWhiteSpace(слово)) { продолжать; } если (wordCounts.ContainsKey(слово)) { wordCounts[слово]++; } еще { wordCounts.Add(слово, 1); } //отменяем выполнение, если была запрошена отмена если (cancellationToken.IsCancellationRequested) { Останавливаться(); выбросить новое OperationCanceledException(); } } //поскольку файлы имеют формат ANSI, мы можем предположить, что на каждый символ приходится 1 байт //при условии, что строки окончаются, поэтому в каждой строке должно быть 2 дополнительных символа ProgressedBytes += Line.Length + 2; //умножаем на 100 как число с плавающей запятой, чтобы не потерять значения запятых int ProgressPercentage = (int) (progressedBytes * 100f / totalBytes); ProgressChanged?.Invoke(this, new ProgressChangedEventArgs(progressPercentage, null)); //отменяем выполнение, если была запрошена отмена если (cancellationToken.IsCancellationRequested) { Останавливаться(); выбросить новое OperationCanceledException(); } линия = ждут читателя.ReadLineAsync(); } читатель?.Dispose(); } var returnValue = wordCounts.OrderByDescending(wordCount => wordCount.Value); Запуск = ложь; вернуть returnValue; } публичная недействительность Стоп() { Запуск = ложь; читатель?.Dispose(); } } }
Я создаю простое приложение, которое подсчитывает слова в файлах. Я выбрал blazor, потому что хотел опробовать его и потому что поддерживать отзывчивость интерфейса относительно легко.
У меня есть сервис для выполнения реальной работы. В своем пользовательском интерфейсе я вызываю службу следующим образом:
private async void InputFileChanged(InputFileChangeEventArgs e) { если (Сервис.Работает) { возвращаться; } IReadOnlyList files = e.GetMultipleFiles(); пытаться { cancelTokenSource = новый CancellationTokenSource (); wordCounts = ждут Service.GetWordCounts(files, cancelTokenSource.Token); ПрогрессПроцент = 100; } поймать (OperationCanceledException ex) { Сервис.Стоп(); wordCounts = ноль; ПрогрессПроцент = 0; } СостояниеИзменено(); } Теперь вы можете заметить Service.Stop(); внутри блока catch. Именно это меня и не радует.
По сути, при отмене процесса обслуживания служба выдает исключение, как это обычно бывает с токенами отмены. При выдаче исключения я уже вызываю этот метод Stop(). Однако служба, похоже, никогда не достигает блоков кода, содержащих throw, даже несмотря на то, что она генерирует исключение. Я проверил с помощью точек останова, и он никогда не прерывается при вызовах внутри службы.
Есть идеи о том, что я делаю неправильно или что я могу улучшить, чтобы не вызывать этот метод Stop() вне службы?
FileCounterService:
с использованием Microsoft.AspNetCore.Components.Forms; использование System.ComponentModel; пространство имен FileWordCounter.Service { общедоступный класс FileCounterService { public bool Running { get; частный набор; } публичное событие ProgressChangedEventHandler? ПрогрессИзменен; частный StreamReader? читатель = ноль; частный длинный totalBytes; частный длинный ProgressedBytes; public async Task GetWordCounts( файлы IEnumerable, Токен отмены (Token отмены) { //инициализируем сервис Запуск = правда; Dictionary wordCounts = новый Dictionary(); //сбрасываем значения прогресса totalBytes = files.Sum(x => x.Size); прогресседбайтс = 0; //прокручиваем каждый файл foreach (файл IBMrowserFile в файлах) { //максимальный размер файла 1 ГиБ должен охватывать большинство файлов клиентов длинный maxFileSize = 1024L * 1024 * 1024 * 1024; пытаться { читатель = новый StreamReader(file.OpenReadStream(maxFileSize, cancelToken)); } поймать (OperationCanceledException ex) { Останавливаться(); бросить бывшего; } нить? линия = ждут читателя.ReadLineAsync(); в то время как (строка != ноль) { если (строка == "") { линия = ждут читателя.ReadLineAsync(); продолжать; } строка[] слова = line.Split(' '); foreach (строковое слово в словах) { если (string.IsNullOrWhiteSpace(слово)) { продолжать; } если (wordCounts.ContainsKey(слово)) { wordCounts[слово]++; } еще { wordCounts.Add(слово, 1); } //отменяем выполнение, если была запрошена отмена если (cancellationToken.IsCancellationRequested) { Останавливаться(); выбросить новое OperationCanceledException(); } } //поскольку файлы имеют формат ANSI, мы можем предположить, что на каждый символ приходится 1 байт //при условии, что строки окончаются, поэтому в каждой строке должно быть 2 дополнительных символа ProgressedBytes += Line.Length + 2; //умножаем на 100 как число с плавающей запятой, чтобы не потерять значения запятых int ProgressPercentage = (int) (progressedBytes * 100f / totalBytes); ProgressChanged?.Invoke(this, new ProgressChangedEventArgs(progressPercentage, null)); //отменяем выполнение, если была запрошена отмена если (cancellationToken.IsCancellationRequested) { Останавливаться(); выбросить новое OperationCanceledException(); } линия = ждут читателя.ReadLineAsync(); } читатель?.Dispose(); } var returnValue = wordCounts.OrderByDescending(wordCount => wordCount.Value); Запуск = ложь; вернуть returnValue; } публичная недействительность Стоп() { Запуск = ложь; читатель?.Dispose(); } } }
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Фоновая служба сердечного ритма останавливается после ошибки DestroySurfaces (Android/Java)
Anonymous » » в форуме JAVA - 0 Ответы
- 17 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Фоновая служба сердечного ритма останавливается после выключения экрана (Android/Java)
Anonymous » » в форуме Android - 0 Ответы
- 10 Просмотры
-
Последнее сообщение Anonymous
-