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

Асинхронное программирование, метод Task.Run() для случая создания задачи с получением результата

26.03.2021, 17:39. Показов 1317. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть такой пример
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
         static int Factorial(int n)
        {
            int result = 1;
            for (int i = 1; i <= n; i++)
            {
                result *= i;
            }
            return result;
        }
        // определение асинхронного метода
        static async void FactorialAsync(int n)
        {
            int x = await Task.Run(()=>Factorial(n));
            Console.WriteLine($"Факториал равен {x}");
        }

И в этом примере есть такая строка int x = await Task.Run(()=>Factorial(n));
Почему используется метод класса Task, а не класса Task<TResult>?
Ведь по идее тут нужно было написать так: int x = await Task<int>.Run(()=>Factorial(n)); (это тоже работает)
Понятно, что класс Task<TResult> наследует все методы класса Task.
Но, формально говоря, получается, что метод Task.Run() имеет перегрузку, которая создает и запускает задачу с возвращаемым результатом. Хотя сам класс Task представляет задачу, которая не возвращает результат.
Зачем эта путаница? Или я что-то не так понимаю?
Кто правильно переведёт вот эту фразу из описания метода Task.Run()?
Queues the specified work to run on the ThreadPool and returns a task or Task<TResult> handle for that work.
В русском варианте она записана так
Ставит в очередь заданную работу для запуска в ThreadPool и возвращает задачу или дескриптор Task<TResult> для этой работы.
А описание перегрузки метода Task.Run() - Run(Func<Task>), создающего и запускающего задачу, которая возвращает значение, в переводе написана так
Ставит в очередь указанную работу для запуска в пуле потоков и возвращает прокси для задачи, возвращаемой функцией function.
В оригинале
Queues the specified work to run on the thread pool and returns a proxy for the task returned by function.
Что значит тут слово прокси в русском переводе?
Вообще с классом Task была введена ещё одна путаница - различие между возвращаемым типом и возвращаемым результатом.
Или я не прав?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.03.2021, 17:39
Ответы с готовыми решениями:

Асинхронное программирование: почему в AsyncCallback не указать метод обратного вызова
Доброго времени суток ! Не могу понять вот эту строчку r.BeginGetResponse(new AsyncCallback((IAsyncResult res) =&gt; { }), null);, это...

Task не содержит определение для Run
Task не содержит определение для Run. Что делать?

Программирование МКЭ для одномерного случая
Добрый день, уважаемые пользователи Cyberorum! Столкнулся с проблемой, что в интернете нет нигде ни одного нормального примера...

10
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
27.03.2021, 04:20
Особо не стал вчитываться в ход мыслей.
Предлагаю покапать в этом направлении
C#
1
2
3
4
5
public class Test {
 
   public static TResult ToDo<TResult>(Func<TResult> func) => func();
 
}
C#
1
2
3
4
5
6
7
8
class Program {
 private static int Func(int n) => n;
 
static void Main() {
 int test = Test.ToDo(() => Func(5));
 Console.WriteLine(test);
}
}
1
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
27.03.2021, 10:12
Цитата Сообщение от titan4ik Посмотреть сообщение
Почему используется метод класса Task, а не класса Task<TResult>?
Потому что этот статический метод определен в классе Task. Как и множество других вспомогательных методов.
Цитата Сообщение от titan4ik Посмотреть сообщение
это тоже работает
Потому что Task<T> унаследован от Task, поэтому с него тоже можно вызвать этот статический метод.
Цитата Сообщение от titan4ik Посмотреть сообщение
Что значит тут слово прокси в русском переводе?
Все очень просто: Func<Task> Возращает ЗАДАЧУ. Это не делегат, который нужно выполнить, а именно внешняя задача, которая ставится в очередь на обработку в пулл (к слову, она может быть уже и завершенная). А под прокси подразумевается что вам возращает не прям результат выполнения Func<Task>, а обертка над ним.
Цитата Сообщение от titan4ik Посмотреть сообщение
Зачем эта путаница?
Это с недопонимания и непривычки. Асинхронное програмирование не самая тривиальная тема, с практикой дойдет что к чему и зачем.

Добавлено через 18 минут
https://stackoverflow.com/ques... -signature

The Run<TResult>(Func<Task<TResult>>) method is used by language compilers to support the async and await keywords. It is not intended to be called directly from user code.
1
Заблокирован
27.03.2021, 10:47  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
А под прокси подразумевается что вам возращает не прям результат выполнения Func<Task>, а обертка над ним.
ОК.
Цитата Сообщение от Wolfdp Посмотреть сообщение
Асинхронное програмирование не самая тривиальная тема
Пофилософствую.
По факту - да, "не самая тривиальная". Но по сути, скажу я вам. что и не особо сложная, когда уже разобрался (в чем-то или совсем со со всем).

Не по теме:

По сути все темы из области программирования не особо сложные - каждая их них это некие три сосны, которые нужно узнать понять и не плутать в них. Асинхронное программирование - не три, а пять или чуть больше этих сосен.
Физика или математика или медицина неизмеримо сложнее. Но с программированием большие проблемы именно при овладении темой. Это связано с плохим (с дидактической точки зрения) качеством изложения в книгах (к тому же - переводных, как правило) и с постоянными изменениями. Учебные материалы не поспевают и/или плохого качества. А справочные материалы хороши именно как справочные, а не при овладении темой. Весьма показательно, что документация официальная (весьма разношерстная по структуре) ввиду всех описанных проблем и понимания их, представляет собой некий гибрид справочной информации и учебника.



Добавлено через 2 минуты
Цитата Сообщение от Wolfdp Посмотреть сообщение
с практикой дойдет что к чему и зачем.
Да, очень занимательно писать примерчики и удивляться результатам тестов)
0
27.03.2021, 11:04

Не по теме:

Цитата Сообщение от titan4ik Посмотреть сообщение
Но по сути, скажу я вам. что и не особо сложная
Ага, ровно до момента когда начинаешь дебажить многоуровневый асинхроный код и по стеку фиг поймешь откуда вызов, и куда все это дело приведет. Ну и обеспечение потокобезопасности, это вообще элементарщина если нужно получить плавающий баг.

0
Заблокирован
27.03.2021, 11:33  [ТС]
Wolfdp, "богат могучив русский языка" и c# - тоже не тупе) Да, разобраться с тем, что можно наворотить с помощью асинхронных возможностей c# - не просто)
Я имел ввиду основы этого языка в части асинхронности. Основы - всегда три или чуть более сосен. Но и их познать не просто) А должно быть просто!)

Добавлено через 20 минут
Wolfdp,
раз уж такая пьянка... Ещё вопрос. Попадалась информация, что поведение асинхронного кода может разниться для приложений разного типа. Например, для приложения WPF и для консольного (из-за специфики основных потоков). В NET 5 эта особенность осталась или нет?
Я имею ввиду такую проблему - отлаживаешь модель в консольном приложении, а потом в WPF она ведет себя "несколько иначе".
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
27.03.2021, 12:35
Цитата Сообщение от titan4ik Посмотреть сообщение
отлаживаешь модель в консольном приложении, а потом в WPF она ведет себя "несколько иначе".
Впервые слышу об этом.
1
Заблокирован
27.03.2021, 16:31  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
Впервые слышу об этом.
Это хорошо, значит проблемы нет или она не столь велика.

Добавлено через 3 часа 17 минут
Цитата Сообщение от EveKS Посмотреть сообщение
public static TResult ToDo<TResult>(Func<TResult> func) => func();
EveKS,
а где описан такой синтаксис?
Он, конечно, работает. Но можно ли увидеть официальное описание такого применения лямбд?
Лямбды везде описываются как средство инициализации делегатов (лямбда создает анонимный метод, на который ссылается экземпляр делегата). А тут с помощью лямбды определяется метод. Я не против) Тем паче, что все работает. Но где описана возможность такого применения лямбд?!

Добавлено через 9 минут
P.S.
То бишь, понятно, что ваш код определения метода вроде как эквивалентен такому коду:
C#
1
2
3
4
public static TResult ToDo<TResult>(Func<TResult> func)
{
    return func();
}
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
27.03.2021, 17:13
titan4ik,
Цитата Сообщение от titan4ik Посмотреть сообщение
Ведь по идее тут нужно было написать так: int x = await Task<int>.Run(()=>Factorial(n));
У нас начал таять снег. Или еще какую инфу мне раскажете?) к чему мне эти выводы?
Человек int потерял. Я ему показал, как его потерять, не только в Task

Добавлено через 11 минут
для общего развития

C#
1
2
3
4
5
        public static Task<TResult> Run<TResult>(Func<TResult> function)
        {
            return Task<TResult>.StartNew(null, function, default,
                TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default);
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        internal static Task<TResult> StartNew(Task? parent, Func<TResult> function, CancellationToken cancellationToken,
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
        {
            if (function == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
            }
            if (scheduler == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
            }
 
            // Create and schedule the future.
            Task<TResult> f = new Task<TResult>(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
 
            f.ScheduleAndStart(false);
            return f;
        }
C#
1
2
3
4
5
        internal Task(Func<TResult> valueSelector, Task? parent, CancellationToken cancellationToken,
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler) :
            base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
        {
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        internal Task(Delegate action, object? state, Task? parent, CancellationToken cancellationToken,
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler)
        {
            if (action == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }
 
            // Keep a link to the parent if attached
            if (parent != null && (creationOptions & TaskCreationOptions.AttachedToParent) != 0)
            {
                EnsureContingentPropertiesInitializedUnsafe().m_parent = parent;
            }
 
            TaskConstructorCore(action, state, cancellationToken, creationOptions, internalOptions, scheduler);
 
            Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
                "Captured an ExecutionContext when one was already captured.");
            CapturedContext = ExecutionContext.Capture();
        }
C#
1
2
3
4
5
6
7
        internal void TaskConstructorCore(Delegate? action, object? state, CancellationToken cancellationToken,
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler)
        {
            m_action = action;
            m_stateObject = state;
            m_taskScheduler = scheduler;
//...
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        internal virtual void InnerInvoke()
        {
            // Invoke the delegate
            Debug.Assert(m_action != null, "Null action in InnerInvoke()");
            if (m_action is Action action)
            {
                action();
                return;
            }
 
            if (m_action is Action<object?> actionWithState)
            {
                actionWithState(m_stateObject);
                return;
            }
            Debug.Fail("Invalid m_action in Task");
        }
0
Заблокирован
27.03.2021, 17:29  [ТС]
Цитата Сообщение от EveKS Посмотреть сообщение
Человек int потерял.
Где, кто потерял? Ничего не понимаю.
Цитата Сообщение от EveKS Посмотреть сообщение
У нас начал таять снег.
У нас уже растаял.
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
27.03.2021, 18:24
titan4ik, это больше к тс
Цитата Сообщение от titan4ik Посмотреть сообщение
И в этом примере есть такая строка int x = await Task.Run(()=>Factorial(n));
Почему используется метод класса Task, а не класса Task<TResult>?
Ведь по идее тут нужно было написать так: int x = await Task<int>.Run(()=>Factorial(n)); (это тоже работает)
Понятно, что класс Task<TResult> наследует все методы класса Task.
C#
1
public class Task<TResult> : Task
От части тс, разобрался
Действительно Task<TResult> : Task

Но сам Run находится в Task. Коротый уже вызывает Task<TResult>.StartNew
C#
1
2
3
4
5
        public static Task<TResult> Run<TResult>(Func<TResult> function)
        {
            return Task<TResult>.StartNew(null, function, default,
                TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default);
        }
Почему Task<TResult> Run<TResult> не в Task<TResult>, видимо так было нужно. Да и так проще, чем писать Task<int>. Ведь под копотом петода Run Task вызовится Task<T> (речь о Func)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.03.2021, 18:24
Помогаю со студенческими работами здесь

Алгоритм Свена и метод дихотомии для двумерного случая
Добрый день. Прошу помочь с переделкой алгоритма Свена для двумерного случая. Дихотомию уже переделала, осталось только Свена. ...

Отмена Task.run
Доброго времени суток! Помогите, пожалуйста, с решением задачи. Пишу программу для взаимодействия с ардуино с асинхронным выполнением...

Внешняя программа с получением результата?
Нужно будет организовать выполнение внешних команд (разархивация и архивация). Код нашелся, работает. Process compiler...

Использовать значение из Task.Run
Привет всем! Подскажите как правильно выстроить логику: у меня есть ф-ия ReadBarcode(), которая вызывает ReadTwoScanners() и...

Как отменить Task.Run?
у меня есть алгоритм, который работает асинхронно и по завершении работы начинает работать заново. как прекратить его работу в любой момент...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это дополнительная запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru