Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
3 / 3 / 1
Регистрация: 24.02.2024
Сообщений: 131

Корректна ли обёртка асинхронной задачи над синхронной?

26.03.2024, 09:26. Показов 2319. Ответов 26

Студворк — интернет-сервис помощи студентам
Доброе утречко!

Есть несколько разных возможностей метода сохранения, и задолбался писать спагетти-код, хочу создать отдельный метод, в котором будет лог о удачном и неудачном сохранении.
Но нужно 2 метода один синхронный, второй асинхронный.
Код компилируется, но мне интересно, вообще правильный ли это подход, и всегда ли будет корректно это работать?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        protected async Task<Result> TrySaveAsync(Func<Task> save)
        {
            return await Task.Run(() => TrySave(async () => await save()));
        }
 
        protected Result TrySave(Action save)
        {
            try
            {
                save();
 
                string message = $"Всё ок";
                _Logger?.LogInformation(message);
                return Result.Ok().WithSuccess(message);
            }
            catch (Exception ex)
            {
                string error = $"Не ок";
                _Logger?.LogError(ex, error);
                return Result.Fail(new Error(error).CausedBy(ex));
            }
        }

Больше беспокоит, будет ли корректно вызываться асинхронный метод, ведь мы его в итоге выполним в синхронном?

C#
1
2
3
4
public async Task Save()
{
       await TrySaveAsync(async () => await MyMethodAsync());
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.03.2024, 09:26
Ответы с готовыми решениями:

Отличие BackgroundWorker от асинхронной (синхронной) многопоточности
Добрый День! Объясните в чем разница между BackgroundWorker и простой многопоточностью, реализуемой Invoke/BeginInvoke. BackgroundWorker...

Обертка над INotifyPropertyChanged
Я пытаюсь написать (если это возможно) обертку над INotifyPropertyChanged. Просто во первых при его реализации в классах приходится писать...

Обертка над C библиотекой
Всем здравствуйте. Есть dll написанная на C и заголовочные файлы. Хочу написать обертку на C++/CLI, чтобы в дальнейшем использовать в C#....

26
3 / 3 / 1
Регистрация: 24.02.2024
Сообщений: 131
27.03.2024, 08:49  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это в какой-то мере нарушение ОПП.
Функция метод "Сохранить", а не посылать сообщения пользователю.
Эта функция относится к Бизнес Логике (Модели).
А выводить сообщения пользователю - это функция UI (Представления).
Обычно примеры везде такие, что метод Save выполняется без try catch, а при вызове его оборачиваем в try catch.

C#
1
2
3
4
5
6
7
8
9
10
var service = new Service(...);
try {
     await service.SaveAsync();
}
catch (Exception ex)
{
     // тут обрабатываем ошибку ex
     // допустим покажем пользователю
    Show(ex.Message);
}
И так делать, во всех местах, откуда вызывается service.SaveAsync(); или service.Save(); и т.д.
Я пытаюсь отловить ошибку в самом низу, и если она понадобится кому-то выше, то передать её через Result (до востребования)
И теперь вызовы метода выглядят компактнее и чище, а вывод пользователю может содержать больше данных, чем стандартный Exception.
C#
1
2
3
4
5
6
7
8
9
10
var service = new Service(...);
var result = await service.SaveAsync();
if (result.IsFailed)
{
     // допустим покажем пользователю
     foreach (var error in result.Errors)
     {
            Show(error.Message);
     }
}
Но часто бывает, что этого хватит просто записать в лог, и не показывать пользователю, тогда вообще вызов будет вот таким

C#
1
2
var service = new Service(...);
await service.SaveAsync();
И не нужно переживать, что будет исключение, мы его отловили, и залогировали.

То есть по сути, хочу избавиться от try catch и Exception в UI совсем.


Цитата Сообщение от IamRain Посмотреть сообщение
Это синхронный код, несмотря на то, что возвращает Task.
Да, я не обратил внимания, что там нет async, в случае с async только await Task.ComplitedTask; можно вернуть.
Так никогда не делал, сейчас проверил, получается ещё одна странная конструкция .
async у метода нет, но вызывать его можно с await и он всё равно дожидается выполнения

Я правильно понимаю, метод возвращающий Task без использования async это возможность синхронный код интегрировать в асинхронную модель?
Это вместо await Task.Run(() => ...);?

Подскажите на примере ClosedXML.
Есть у меня приложение и мне нужно прочесть excel 1Gb.
У библиотеки ClosedXML нет асинхронных методов, но читает она его очень долго, поэтому дождаться выполнения обязательно нужно.
В таком случае мне код лучше создавать в методе, возвращающем Task без использования async?
Или же весь код по чтению файла обернуть в await Task.Run(()=> );

Цитата Сообщение от IamRain Посмотреть сообщение
Вам надо вникнуть в ментальную модель async/await, а на это потребуется время. Идея такая - использовать потоки всегда, пока это имеет смысл.
Да, всё хорошо, до слова "пока"
А вот потом пока это имеет смысл



Цитата Сообщение от HF Посмотреть сообщение
И что же... уже начинают обсуждать чтобы сделать это в .NET9.
Сделают необязательным?
А как же синхронные методы, как их отличить не то что разработчику, а компилятору?
0
 Аватар для Andrey-MSK
3397 / 2283 / 388
Регистрация: 14.08.2018
Сообщений: 7,767
Записей в блоге: 4
27.03.2024, 09:22
Цитата Сообщение от gazed Посмотреть сообщение
То есть по сути, хочу избавиться от try catch и Exception в UI совсем.
Работает такой пользователь, и тут бац - вылет, зависло. Он такой ну ладно, запускает ещё раз - и опять вылет, зависло. Звонит вам и типа у меня не работает. А вы ему всё ништяк, я логи записал, ща править буду...

Никто так не делает... Пользователь должен быть уведомлён о том что что-то произошло и иметь возможность безопасно завершить свою работу с приложением.

Добавлено через 17 минут
gazed, Если уж не хочется руками писать try..catch, то смотрите в сторону вот этого - AppDomain.UnhandledException Событие.

Добавлено через 3 минуты
gazed, И в паре с ним вот это - Application.ThreadException Событие. Для форм.
2
3 / 3 / 1
Регистрация: 24.02.2024
Сообщений: 131
27.03.2024, 17:32  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Работает такой пользователь, и тут бац - вылет, зависло. Он такой ну ладно, запускает ещё раз - и опять вылет, зависло. Звонит вам и типа у меня не работает. А вы ему всё ништяк, я логи записал, ща править буду...
Второй блок кода, показываем ошибку пользователю, переданный через errors, не просто exception, а уже описанная ошибка, которую один раз только описали в корне. И сам Exception тоже есть в объекте Error, если вдруг нужен.
То есть сам Exception ни куда не делся, просто не хочу постоянно отлавливать одну и ту же ошибку.
C#
1
2
3
4
5
6
7
8
9
10
var service = new Service(...);
var result = await service.SaveAsync();
if (result.IsFailed)
{
     // допустим покажем пользователю
     foreach (var error in result.Errors)
     {
            Show(error.Message);
     }
}
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
AppDomain.UnhandledException Событие.
Это как я понимаю глобальное, а я говорю о Exception для определённого действия, где при отлове Exception, я опишу ещё текстом, что это за ошибка была.

p.s. Как я понимаю, так не принято делать, но вот сам язык это позволяет реализовать?

Добавлено через 1 минуту
Как в Minimal API можно выбрасывать Exception, а можно Result в формате, который прочтёт клиент, вместо обычного Exception.
0
HF
 Аватар для HF
1344 / 928 / 202
Регистрация: 09.09.2011
Сообщений: 2,757
Записей в блоге: 2
27.03.2024, 17:58
Цитата Сообщение от gazed Посмотреть сообщение
p.s. Как я понимаю, так не принято делать, но вот сам язык это позволяет реализовать?
Язык то тут причём? Вы создаёте что-то своё, по своим законам и принципам. Язык - инструмент.

Цитата Сообщение от gazed Посмотреть сообщение
Это как я понимаю глобальное, а я говорю о Exception для определённого действия, где при отлове Exception, я опишу ещё текстом, что это за ошибка была.
У меня в винформ написаны декораторы. По сути конвеер этого "определённого действия". Наверное аналог этого - Promise в JavaScript. Вызываете асинхронный метод, куда передаёте основное действие (Action, или как вы там напишите), обработчик успешного завершения и обработчик ошибки.
Если обёрнутый эшен в трай вызовет исключение, то в catch выполнится обработчик ошибки. В котором будет выполнено что вы хотите - разблокировка кнопок, логирование, сообщение об ошибке и т.п. и т.д.

Вообщем фантазия на эту тему не ограничена. Логирование, диалоги, выключение компутера...
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,177
Записей в блоге: 2
27.03.2024, 22:27
Цитата Сообщение от gazed Посмотреть сообщение
Обычно примеры везде такие, что метод Save выполняется без try catch, а при вызове его оборачиваем в try catch.
Метод Show - это уровень Представления (ну, в край вызов в VM внедрённого метода Представления).
Как я вам и сказал выше, что функция обработки исключений это уровень Представления.

Цитата Сообщение от gazed Посмотреть сообщение
И так делать, во всех местах, откуда вызывается service.SaveAsync(); или service.Save(); и т.д.
А вот это неверно.
Так нужно делать только на уровне Представления.

Цитата Сообщение от gazed Посмотреть сообщение
// допустим покажем пользователю
Опять уровень Представления.

Цитата Сообщение от gazed Посмотреть сообщение
И не нужно переживать, что будет исключение, мы его отловили, и залогировали.
Ну, как видите, переживать приходится - иначе не разводили бы этот сыр бор.
Исключение поднялось на уровень Представления, и там его хотите показали пользователю, хотите передали в службу логирования. Это уже функция представления, а не БЛ.

Условно представьте себе:
- Модель работает на Юпитере.
- Презентер/контролер/VM на Луне
- На Земле работает только представление.

Чего и кому будет выводить на Юпитере такая обработка исключений?
Исключение должно быть передано на Землю, чтобы его мог человек посмотреть или записать в какой-то блокнот (логирование), чтобы потом разобраться.

Цитата Сообщение от gazed Посмотреть сообщение
async у метода нет, но вызывать его можно с await и он всё равно дожидается выполнения
для async не обязательно нужен таск.
Типы возвращаемых значений асинхронных операций

Цитата Сообщение от gazed Посмотреть сообщение
метод возвращающий Task без использования async это возможность синхронный код интегрировать в асинхронную модель?
Не только.
Такой код тоже будет выполняться синхронно, хотя и будет выводится предупреждение:
C#
1
2
3
4
5
6
7
        public static async Task Foo1()
        {
            var lines = File.ReadAllLines("file name");
 
            //some logic
 
        }
Цитата Сообщение от gazed Посмотреть сообщение
У библиотеки ClosedXML нет асинхронных методов, но читает она его очень долго, поэтому дождаться выполнения обязательно нужно.
В таком случае мне код лучше создавать в методе, возвращающем Task без использования async?
Или же весь код по чтению файла обернуть в await Task.Run(()=> );
Не путайте асинхронность и паралельность.
Прекрасный пример UI элементы Форм и WPF. Работа с ними может выполняться асинхронно, но никогда не может выполняться параллельно.

Цитата Сообщение от gazed Посмотреть сообщение
То есть сам Exception ни куда не делся, просто не хочу постоянно отлавливать одну и ту же ошибку.
Вы уже много раз упоминаете постоянно отлавливать одну и ту же ошибку.
Во-первых, не путайте ошибки и исключения. Это совершенно разные сущности.
Во-вторых, почему вы считаете что обработка исключений "внизу" уменьшает код? Да, даже если так - это всё равно делает код намного запутаннее и непонятнее. А ГЛАВНОЕ для чего придуман ООП - это сделать код модульным, простым и понятным. Даже если при этом он буде больше, длиннее.

Например, у вас есть какой-то запрос к нестабильной линии.
Если на линии не проходит сигнал - выкидывается исключение.
Но вы делаете несколько попыток.
Вот обработка однократных исключений на уровне БЛ - это перевод исключения в обрабатываемые ошибки.
Но повторили 10 раз, а соединения так и нет. Это уже исключение. И его не надо обрабытывать в БЛ. Его нужно прокинуть вверх для уведомления потребителей.
1
3 / 3 / 1
Регистрация: 24.02.2024
Сообщений: 131
27.03.2024, 23:10  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Во-первых, не путайте ошибки и исключения. Это совершенно разные сущности.
Неправильно выражаюсь, а так я понимаю разницу, и что такое исключения.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Как я вам и сказал выше, что функция обработки исключений это уровень Представления
Вот мне не нравится сам подход с исключениями в UI.
При замене UI эти все исключения нужно создавать заново.
Я не говорю что так неправильно или не хорошо, мне лично не нравится, чтобы UI был загажен и обрабатывал логику.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Условно представьте себе:
- Модель работает на Юпитере.
- Презентер/контролер/VM на Луне
- На Земле работает только представление.
Вот отлично, но по сути у меня на спутнике Юпитера будет ещё базовый класс ServiceBase, который при исключении, отловит его запишет свои дополнительные инструкции, и всем по пузырькам (как-то так по-моему это называется) передаст объект Result внутри которого и лог, и объект исключения, и даже сам результат, если нужен.
И уже любой уровень хоть то Луна, хоть то Земля, может взять эти данные и обработать.
Допустим Луна добавит (если необходимо) туда ещё свои комментарии, в этот же объект Result и передаст уже более точное описание. Или же если Луне пришло исключение, и она может изменить ход событий, то она делает повторную попытку и т.д., но не сама Земля.
И уже последняя Земля выведет и покажет человеку разумному эти сообщения и исключения.
Но сама Земля не беспокоится о exception, а знает, что все возможные исключения, будут отловлены, и доставлены ей на блюдечке с голубой каёмочкой

Вот с такой моделью у меня всё ок было, когда я делал синхронный код, а когда асинхронный, боюсь, чтобы это исключение не застряло где-то на Юпитере или Луне, и что до Земли придёт что всё ок, а на самом деле не ок.
Единственный минут, это то, что всё приложение завязано на FluentResults, который там на всегда.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,177
Записей в блоге: 2
28.03.2024, 21:36
Цитата Сообщение от gazed Посмотреть сообщение
Вот мне не нравится сам подход с исключениями в UI.
Пусть тогда этим занимается App. Но в любом случае это не уровень БЛ.

Цитата Сообщение от gazed Посмотреть сообщение
у меня на спутнике Юпитера будет ещё базовый класс ServiceBase, который при исключении,
Угу.
Но Модель это слой, а не один объект.
А если у вас на каждой планете по своему классу Модели. А если у какой-то планеты нет спутника на котором можно разместить ServiceBase?

Поймите, мы вам не говорим о том, что ваш код не будет работать.
Мы о том, что он неверно скомпонован согласно принципов ООП.
Если вам всё равно их нарушение - то всё ок. "Работает - ну, и ладно".

Добавлено через 15 минут
gazed, ООП это не только спек языка.
На языке многое можно написать.
ООП это в первую очередь про ВЗАИМОПОНИМАНИЕ разработчиков, что особенно важно в коллективном программировании, на которое и нацелено ООП.
А взаимопонимание, в том числе, это и одинаковые подходы к решению одинаковых задач.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.03.2024, 21:36

Обёртка над opengl
Всем доброго. После работы с opengl на С++, захотелось ещё разок попробовать поработать с С#, но из прежнего опыта ни одна из оберток мне...

Обёртка над WinAPI
В архиве обычная обёртка над формой на WinApi, (ничего лишнего только класс формы); Чтобы создать форму в main.cpp объявлен класс MyWnd...

Обертка над Си библиотекой
Добрый день, имеется библиотека написанная на Си (API для работы с оборудованием), хочу обернуть ее в код C#. Вот код написанный на...

Обёртка над WinApi платно
Среда - Code::Blocks_16.01 Я написал обёртку над окном WinApi которая реализует событейную модель. Обёртка работает, написал даже...

GUI обертка над консолью
Господа, доброго времени суток. Пытаюсь сейчас перевести свою консольную программу, в гуи приложение. Никак не могу разобраться как сделать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
27
Ответ Создать тему
Новые блоги и статьи
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru