Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/16: Рейтинг темы: голосов - 16, средняя оценка - 4.69
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923

Синхронизация метода в событии

17.02.2022, 20:06. Показов 3492. Ответов 70
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Проблема 1

Подписался я на какое-то событие. По подписке хочу запускать задачи, но по мере их выполнения.
C#
1
2
3
4
5
private void OnSomethingChanged()
{
    TaskOne();
    TaskTwo();
}
Заawaitить таски, в таком случае, я не могу, ведь по идее async мне никакого толку не даст.

Проблема 2

Есть какой-то конструктор, в которм такая же проблема:
C#
1
2
3
4
5
6
7
8
public class A
{
    public A()
    {
        TaskOne();
        TaskTwo();
    }
}
Если в первом случае я ещё могу сделать что-то типо такого:
C#
1
2
3
4
5
private void OnSomethingChanged() => Task.Run(async () =>
{
    await taskOne();
    await taskTwo();
});
То во втором случае я так уже не сделаю.

Как бы по-уму подойти к этим ситуациям и что мне неизвестно в глубинках Net?

Да и уместно ли прикрутить к этому .GetAwaiter()?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.02.2022, 20:06
Ответы с готовыми решениями:

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

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

Синхронизация метода(пример из книги Г. Шилдт)очерёдность вывода результата не такая как в главном потоке
Всем привет (сори за длинное название темы но не знал как иначе передать суть вопроса). В книге "Шилдт Г. - Java 8. Полное...

70
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
18.02.2022, 16:33
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
т.е. происходит следующее?
Оно, ага.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
А если не используются статические конструкторы, то могут быть случаи зависания из-за Wait(), которых бы в случае await не было бы?
Да, причем весьма часто там, где контекст привязан к потокам — в UI приложениях, например.
1
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 16:44
Цитата Сообщение от kolorotur Посмотреть сообщение
Да, причем весьма часто там, где контекст привязан к потокам — в UI приложениях, например.
Можете привести простенький пример? Не понятно, почему при await не будет взаимных блокировок, а при Wait будут и это не будет связано с статическим конструктором и ConfigureAwait не решит проблему.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
18.02.2022, 17:59
Fylhtq05, я ничего не говорил про ConfigureAwait - он обычно и используется для решения подобных проблем.
2
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 18:22
kolorotur, т.е. если нет статического конструктора, в котором асинхронно вызывается статический метод и во всех случаях стоит АсинхронныйМетод.ConfigureAwait(false).W ait();, то больше никаких неприятностей, связанных с Wait(), нет? Т.е. если нет статического конструктора, то отличие Wait() от await, только в контексте, который решается ConfigureAwait(false)?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,145
Записей в блоге: 2
18.02.2022, 19:12
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
могут быть случаи зависания из-за Wait(), которых бы в случае await не было бы?
Очень часто в WPF (и в Формах, думаю, тоже), когда из-за Wait происходит неюная взаимоблокировка.
1
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 19:28
Элд Хасп, можете привести пример, чтобы не было статического конструктора, вызывающего асинхронно статический метод, но были бы зависания из-за Wait(), несмотря на применение ConfigureAwait, которые бы исчезали при модификации кода для замены Wait() на await.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,145
Записей в блоге: 2
18.02.2022, 19:39
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
можете привести пример
C#
1
2
3
4
        private void OnClick(object sender, RoutedEventArgs e)
        {
            Task.Run(() => Dispatcher.Invoke(() => tBlock.Text = "Какой-то текст")).Wait();
        }
1
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 20:07
Элд Хасп, что такое Dispatcher?
ConfigureAwait не помогает, а замена на await решает проблему?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,145
Записей в блоге: 2
18.02.2022, 20:19
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
что такое Dispatcher?
Это из WPF.
Используется для доступа к UI элементам из других потоков.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
замена на await решает проблему?
Да.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
ConfigureAwait не помогает
Он имеет значение ПОСЛЕ выполнения задачи, а блокировка происходит внутри задачи.
То есть до него исполнение даже не доходит.
1
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 20:25
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это из WPF.
Немного знаю только формы. А можете рассказать что происходит и почему блокировка.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
18.02.2022, 20:29
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
т.е. если нет статического конструктора, в котором асинхронно вызывается статический метод и во всех случаях стоит АсинхронныйМетод.ConfigureAwait(false).W ait();, то больше никаких неприятностей, связанных с Wait(), нет?
Нет, пример со статическим конструктором — заковыристый случай, но далеко не единственный.

Вот более реалистичный пример.
Ниже метод из сторонней сборки, который изменить нельзя:
C#
1
2
3
4
5
6
public async Task MethodFromAnotherLibrary()
{
    await Task.Delay(1000);
    Application.Current.MainWindow.Title = "Готово!";
    MessageBox.Show("Первое");
}
Вам надо этот метод вызвать по клику по кнопке так, чтобы ничего не повисло, не закрашилось и сообщение "Второе" вышло после сообщения "Первое":
C#
1
2
3
4
5
private void Button_Click(object sender, RoutedEventArgs e)
{
    MethodFromAnotherLibrary();
    MessageBox.Show("Второе");
}
Кошерный вариант (минус пара очков за отсутствие try/catch в async void-методе):
C#
1
2
3
4
5
private async void Button_Click(object sender, RoutedEventArgs e)
{
    await MethodFromAnotherLibrary();
    MessageBox.Show("Второе");
}
Без await становится весело.
3
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 20:46
kolorotur, то что без await сначала выводится "Второе" - так и должно быть. Wait() здесь можно применить? Если нельзя, почему (что-то связано с тем, что метод в dll и потому опять какие-то особенности языка?)?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
18.02.2022, 20:57
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
то что без await сначала выводится "Второе" - так и должно быть.
В том-то и дело, что не должно.
Где же это видано, чтобы первое было после второго?!

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
Wait() здесь можно применить? Если нельзя, почему (что-то связано с тем, что метод в dll и потому опять какие-то особенности языка?)?
Я специально сделал оба метода максимально простыми, чтобы их можно было без изменений скопировать в пустой проект на WPF и всячески поиграться.
Надо только добавить кнопку в окошко и привязать к ней обработчик Button_Click.
С DLL связано только то, что вы этот метод не можете изменить — его уже за вас написал другой разработчик.
Ну, чтобы соблазна не было
2
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
18.02.2022, 21:00  [ТС]
Wait -- замораживает поток, полностью останавливая всё WPF приложение до завершения задачи.

Не все приложение, а только текущий поток.
kolorotur, спасибо что поправили. Выразился не профессионально. Я имел ввиду, если это Dispatcher — окно будет полностью неактивным*/некликабельным.

Хорошо. Разобрался что делает .ConfigureAwait(false). Где я могу это применить? Опять же: на примере WPF проекта. Как я понимаю это точно не слой View/ViewModel. Видимо где-то в Model.
0
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 21:05
Цитата Сообщение от kolorotur Посмотреть сообщение
В том-то и дело, что не должно.
У вас же await Task.Delay(1000); потому внутри самого метода происходит ожидание, а в это время выполняется метод, который печатает "Второй". После секунды ожидания и первый метод печатает "Первый". Что не так в этих рассуждениях? Можете поправить пример, чтобы я проверил в формах? В них нет Application.Current.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,145
Записей в блоге: 2
18.02.2022, 21:47
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
Немного знаю только формы.
Это (примерно) аналог Control.Invoke из Форм.
Если использовать его в формах подробным же образом, думаю, там тоже будет взаимоблокировка.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
А можете рассказать что происходит и почему блокировка.
Кликер вызывается в UI потоке.
Чтобы не загружать UI поток исполнением большого кода, он передаётся в задачу.
Но по какой-то причине есть необходимость дождаться завершения исполнения этого кода.
Поэтому ставится Wait.

Но в самом коде тоже может быть обращение к UI элементам.
Для этого приходится это делать через марщалинг в UI поток.
Поток начнёт исполнять маршалируемле действие, когда освободится.
Но он не может освободиться пока не завершится задача.

В общем случае, вы не знаете, что есть в асинхронном методе.
Есть там маршалинг в UI поток или нет.
Вам известно только что он возвращает задачу (Task).

Если вы ожидаете эту задачу через await, то никаких проблем не будет.
А вот если ожидаете через Wait - возможны нюансы, о которых вы узнаете только косвенно по зависания приложения.
И вы даже понять не сможете, может это метод так долго работает, может в нём ошибка какая-то?
То что это взаимоблокировка может даже в голову не прийти.
2
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
18.02.2022, 21:47
Лучший ответ Сообщение было отмечено limeniye как решение

Решение

Цитата Сообщение от limeniye Посмотреть сообщение
Где я могу это применить? Опять же: на примере WPF проекта.
Там, где задача запускается из UI-потока, но не должна в нем продолжаться.
Это устраняет массу багов с теми же зависаниями и делает приложение более шустрым.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
У вас же await Task.Delay(1000); потому внутри самого метода происходит ожидание
Вот потому его и желательно ожидать через await.
Да и какая разница что там внутри происходит? Вы же когда вызываете какой-нибудь асинхронный метод из .NET — всегда его ждете через await, а не лезете в исходники проверять что там да как.
Пусть там будет не Task.Delay, а DownloadVeryImportantDataWithoutWhichWeC annotContinueAsync — не суть важно.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
а в это время выполняется метод, который печатает "Второй".
Вот он и не должен в это время выполняться.
Допустим, продолжение второго метода зависит от завершения первого метода. Если первый метод скачивает что-нибудь с интернета, с чем второму методу надо потом работать.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
Что не так в этих рассуждениях?
Вы, как всегда, начинаете придираться к примеру вместо того, чтобы попытаться понять принципы, для демонстрации которых этот пример создавался.

Цитата Сообщение от Fylhtq05 Посмотреть сообщение
В них нет Application.Current.
Замените на любой код, который меняет что-нибудь в UI.
3
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 22:22
Цитата Сообщение от kolorotur Посмотреть сообщение
Замените на любой код, который меняет что-нибудь в UI.
Сделал. Да, Wait не работает. Теперь бы понять почему не работает и почему не удается применить ConfigureAwait?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16150 / 11271 / 2890
Регистрация: 21.04.2018
Сообщений: 33,145
Записей в блоге: 2
18.02.2022, 22:42
Цитата Сообщение от Fylhtq05 Посмотреть сообщение
почему не удается применить ConfigureAwait?
Чё вы к нему прицепились?
Он, вообще, не имеет никакого отношения к блокировке.
ОН может повлиять, допустим, на исключения в коде выполняющимся ПОСЛЕ завершения задачи.
0
109 / 52 / 16
Регистрация: 09.06.2021
Сообщений: 480
18.02.2022, 23:00
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Чё вы к нему прицепились?
Да я как-то писал код на формах. Без него не работало, а с ним стало все нормально.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.02.2022, 23:00
Помогаю со студенческими работами здесь

Невозможно передать ArrayList в аргументы метода без модификатора static у этого метода или метода main
Крч, хочу передать экземпляр класса ArrayList в метод, но ide говорит, что нельзя это сделать, пока сам метод или main не будут в...

Модуль EVO II синхронизация 50гц, На какой ножке контроллера синхронизация шим двигателя?
Частый дефект для модулей EVO II с коллекторным двигателем - нет управления двигателем при помехах в сети. Помехи создают диммеры, блоки...

Полиморфизм: вызов метода базового класса, переопределенного метода и нового метода
В базовом классе метод помечен как virtual. Насколько я понял из книги: override означает, что метод не утрачивает связи с базовым...

Комбинирование метода половинного деления, метода хорд и метода касательных
Помогите пожалуйста. Нужно написать программу, которая совмещала в себе три метода : метод хорд, касательных и половинного деления....

Как из метода отправить переменную в другой метод и продолжить выполнение метода?
Здравствуйте, подскажите пожалуйста, как из метода отправить переменную в другой метод и продолжить выполнение метода? static string...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru