Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
2395 / 1924 / 763
Регистрация: 27.07.2012
Сообщений: 5,569

Синхронный вызов асинхронной функции

21.09.2022, 12:18. Показов 1416. Ответов 10
Метки нет (Все метки)

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

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

Небольшой пример.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
 
interface IMenuItem
{
    void Execute();
}
 
class ActionMenuItem : IMenuItem
{
    public ActionMenuItem(Action a) => action = a;
    public void Execute() => action();
    private Action action;
}
 
class Program
{
    static void Main()
    {
        List<IMenuItem> menu = new List<IMenuItem>
        {
            new ActionMenuItem(AsyncMethod),
            new ActionMenuItem(SyncMethod)
        };
        
        menu[0].Execute();
        menu[1].Execute();
        
        Console.ReadLine();
    }
    
    static async void AsyncMethod()
    {
        await Task.Delay(1000);
        Console.WriteLine("async");
    }
    
    static void SyncMethod()
    {
        Console.WriteLine("sync");
    }
}
Он выведет на печать сначала "sync", а потом "async", что логично, так как асинхронный метод здесь выполняется дольше, хотя методы вызваны в другом порядке. Во что можно обернуть AsyncMethod, чтобы он всё же был вызван синхронно?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.09.2022, 12:18
Ответы с готовыми решениями:

Как правильно блокировать повторный запуск асинхронной функции ?
Допустим есть асинхронная функция, вызываемая по нажатию кнопки пользователем. Функция не быстрая, ходит по http Как можно запретить...

Ожидание в асинхронной функции ввода текста в TextBox (наподобие консольной readline)
Есть асинхронная функция, в середине которой требуется дать пользователю доступ к текстбоксу и и ожидать допустим нажатия кнопки для...

Корректный синхронный вызов асинхронного метода
Всем привет. Подскажите, корректно ли вот так превращать асинхронный вызов в синхронный? public static T WaitResult&lt;T&gt;(this...

10
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16142 / 11265 / 2888
Регистрация: 21.04.2018
Сообщений: 33,127
Записей в блоге: 2
21.09.2022, 13:09
Лучший ответ Сообщение было отмечено John Prick как решение

Решение

Цитата Сообщение от John Prick Посмотреть сообщение
Во что можно обернуть AsyncMethod, чтобы он всё же был вызван
C#
23
           new ActionMenuItem(() =>AsyncMethod().Wait()),
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
21.09.2022, 16:57
Лучший ответ Сообщение было отмечено John Prick как решение

Решение

John Prick, я бы сделал наоборот: по умолчанию предполагать, что обработчик асинхронный (т.е. Func<Task> вместо Action и await в цикле), а синхронные реализации могут вернуть завершенную таску.
Многих проблем избежите, плюс не придется потоки по чем зря блочить.
3
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16142 / 11265 / 2888
Регистрация: 21.04.2018
Сообщений: 33,127
Записей в блоге: 2
21.09.2022, 17:11
John Prick, кстати, обратил внимание только после сообщения от kolorotur.
У вас метод AsyncMethod() void, а не Task.
Wait() можно применить только к Task.
Узнать когда завершиться void асинхронный метод, насколько знаю, нельзя.
1
2395 / 1924 / 763
Регистрация: 27.07.2012
Сообщений: 5,569
21.09.2022, 21:08  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
У вас метод AsyncMethod() void, а не Task.
Wait() можно применить только к Task.
Да, это я, конечно, понял. Ваш вариант работает, это хорошо. Другое дело, что в реальном коде для action перехватываются исключения, а в таком варианте они выпускаются наружу.

Цитата Сообщение от kolorotur Посмотреть сообщение
я бы сделал наоборот: по умолчанию предполагать, что обработчик асинхронный (т.е. Func<Task> вместо Action и await в цикле), а синхронные реализации могут вернуть завершенную таску.
Возможно, но придётся много рутинной работы сделать для всех обработчиков.

Добавлено через 4 минуты
Как-то так:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
 
interface IMenuItem
{
    Task Execute();
}
 
class FuncTaskMenuItem : IMenuItem
{
    public FuncTaskMenuItem(Func<Task> f) => func = f;
    public string Name { get; set; }
    public async Task Execute()
    {
        try
        {
            await func();
        }
        catch (Exception)
        {
            Console.WriteLine("Error");
        }
    }
    private Func<Task> func;
}
 
class Program
{
    static void Main()
    {
        MainBody();
        Console.ReadLine();
    }
    
    static async void MainBody()
    {
        List<IMenuItem> menu = new List<IMenuItem>
        {
            new FuncTaskMenuItem(AsyncMethod),
            new FuncTaskMenuItem(SyncMethod),
            new FuncTaskMenuItem(ExceptionMethod)
        };
        
        await menu[0].Execute();
        await menu[1].Execute();
        await menu[2].Execute();
    }
    
    static async Task AsyncMethod()
    {
        await Task.Delay(1000);
        Console.WriteLine("async");
    }
    
    static Task SyncMethod()
    {
        Console.WriteLine("sync");
        return Task.CompletedTask;
    }
    
    static Task ExceptionMethod()
    {
        throw new Exception();
    }
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16142 / 11265 / 2888
Регистрация: 21.04.2018
Сообщений: 33,127
Записей в блоге: 2
21.09.2022, 21:19
Цитата Сообщение от John Prick Посмотреть сообщение
Другое дело, что в реальном коде для action перехватываются исключения, а в таком варианте они выпускаются наружу.
Не понял.
Wait подымает исключение, если оно было в таске.
Покажите на простом примере, что вы имеете ввиду.
0
2395 / 1924 / 763
Регистрация: 27.07.2012
Сообщений: 5,569
21.09.2022, 21:26  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не понял.
Wait подымает исключение, если оно было в таске.
Да, пардон, это я не туда посмотрел. Не все исключения перехватывались, как оказалось.

Вот пример, для полноты картины:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
 
interface IMenuItem
{
    void Execute();
}
 
class ActionMenuItem : IMenuItem
{
    public ActionMenuItem(Action a) => action = a;
    public void Execute()
    {
        try
        {
            action();
        }
        catch (Exception)
        {
            Console.WriteLine("Error");
        }
    }
    private Action action;
}
 
class Program
{
    static void Main()
    {
        List<IMenuItem> menu = new List<IMenuItem>
        {
            new ActionMenuItem(() => AsyncMethod().Wait()),
            new ActionMenuItem(SyncMethod),
            new ActionMenuItem(ExceptionMethod)
        };
        
        menu[0].Execute();
        menu[1].Execute();
        menu[2].Execute();
        
        Console.ReadLine();
    }
    
    static async Task AsyncMethod()
    {
        await Task.Delay(1000);
        Console.WriteLine("async");
    }
    
    static void SyncMethod()
    {
        Console.WriteLine("sync");
    }
    
    static void ExceptionMethod()
    {
        throw new Exception();
    }
}
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,234
21.09.2022, 21:43
John Prick, видимо, проблема была в async void - эти методы должны сами обрабатывать возникающие исключения, так как они не пробрасывают исключения вверх по стеку. (так как они не await-ятся, а проброс реализован именно через механизм ожидания - await или Wait()).
Надо это просто помнить.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16142 / 11265 / 2888
Регистрация: 21.04.2018
Сообщений: 33,127
Записей в блоге: 2
22.09.2022, 07:37
Цитата Сообщение от John Prick Посмотреть сообщение
Вот пример, для полноты картины:
Дополнил примером с исключением в задаче:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using System.Runtime.CompilerServices;
 
namespace Core2022.JohnPrick
{
    public interface IMenuItem
    {
        void Execute();
    }
 
    public class ActionMenuItem : IMenuItem
    {
        public ActionMenuItem(Action a) => action = a;
        public void Execute()
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        private Action action;
    }
 
    public class MenuItemTest
    {
        public static void Start()
        {
            List<IMenuItem> menu = new List<IMenuItem>
            {
                new ActionMenuItem(() => AsyncMethod().Wait()),
                new ActionMenuItem(() => AsyncExceptionMethod().Wait()),
                new ActionMenuItem(SyncMethod),
                new ActionMenuItem(ExceptionMethod)
            };
 
 
            for (int i = 0; i < menu.Count; i++)
            {
                Console.Write($"{i}) ");
                menu[i].Execute();
                Console.WriteLine();
            }
 
            Console.ReadLine();
        }
 
        static async Task AsyncMethod()
        {
            await Task.Delay(1000);
            MethodNameWrite();
        }
 
        static void SyncMethod()
        {
            MethodNameWrite();
        }
        static async Task AsyncExceptionMethod()
        {
            await Task.Delay(1000);
            MethodNameWrite();
            ExceptionMethod();
        }
 
        static void ExceptionMethod()
        {
            MethodNameWrite();
            throw new Exception();
        }
 
        public static void MethodNameWrite([CallerMemberName] string? memberName = null)
        {
            Console.WriteLine(memberName);
        }
    }
}
Консоль0) AsyncMethod

1) AsyncExceptionMethod
ExceptionMethod
One or more errors occurred. (Exception of type 'System.Exception' was thrown.)

2) SyncMethod

3) ExceptionMethod
Exception of type 'System.Exception' was thrown.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16142 / 11265 / 2888
Регистрация: 21.04.2018
Сообщений: 33,127
Записей в блоге: 2
22.09.2022, 08:09
John Prick, кстати, добавьте перегрузку в ActionMenuItem:
C#
10
11
12
13
    public class ActionMenuItem : IMenuItem
    {
        public ActionMenuItem(Action action) => this.action = action;
        public ActionMenuItem(Func<Task> task) => action = () => task().Wait();
И его станет удобнее использовать для асинхронных методов:
C#
32
33
34
35
36
37
38
            List<IMenuItem> menu = new List<IMenuItem>
            {
                new ActionMenuItem(AsyncMethod),
                new ActionMenuItem(AsyncExceptionMethod),
                new ActionMenuItem(SyncMethod),
                new ActionMenuItem(ExceptionMethod)
            };
1
2395 / 1924 / 763
Регистрация: 27.07.2012
Сообщений: 5,569
22.09.2022, 09:01  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
добавьте перегрузку в ActionMenuItem
Да, я уже по-всякому тут поэкспериментировал ) Спасибо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.09.2022, 09:01
Помогаю со студенческими работами здесь

Использование асинхронной функции синхронно
Добрый день. Да, я знаю что так делать не желательно, но уже очень нужно. У меня на примете есть несколько вариантов, да и вообще хотелось...

Синхронный счетчик с асинхронной загрузкой
Добрый день. У меня есть программа, все правильно вроде, но при симуляции происходит странная вещь, счетчик сначала считает правильно, а...

Не удается выполнить исходящий вызов, так как приложение обрабатывает входящий синхронный вызов
И снова добренького вечера) Столкнулся с такой проблемой, может кто знает пути выхода из нее. Есть процедура чтения свойств флешки: ...

Синхронный вызов метода
Как сделать синхронный вызов WCF Я создаю службу WCF, объявляю контракт с атрибутом ServiceContract, в нем несколько методов с атрибутом...

Получить значение из асинхронной функции
Здравствуйте. Помогите мне пожалуйста. Нужно вернуть с помощью return значение глобальной переменной b. Но у меня return возвращает...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru