Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 2 3 4 5 6 7 [8] 9 10 11   вперед  Ctrl      все
 Re: Зачем нужен await?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
ВМоисеев
>Petro123, вчера, 19:17 [21633388]
>...Оператор await используется для ожидания.
<Может быть так:
В коде вызывающего метода оператор await используется для ожидания завершения кода вызванного метода. Коды других методов, обработчиков сообщений, могут работать асинхронно.

Это противоречит? Уточняет? Добавляет эмоции?
Зачем ты это написал?
8 авг 18, 10:57    [21634009]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
LR
если вызов async-метода производится не из UI-потока,
это когда нибудь требуется? Или это чисто абстрактно?
8 авг 18, 11:02    [21634020]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5249
Shocker.Pro
kealon(Ruslan)
ConfigureAwait(false) просто разрешает выполнять твой контекст в любом потоке, UI-поток не исключение
ConfigureAwait(false) разрешает выполнять продолжение в том же потоке, но меня пока интересует обратная ситуация...
именно что в любом
true to attempt to marshal the continuation back to the original context captured; otherwise, false.
8 авг 18, 11:12    [21634035]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
LR
Откуда такое заблуждение? Вся та статья как раз и посвящена доказательству того что это не так (что контекст синхронизации не переходит через await, а значит, если вызов async-метода производится не из UI-потока, то и продолжение не будет выполнятся в UI-потоке, что бы там в ConfigureAwait не задавалось).


Зачем ему переходить? И почему заблуждение? Сейчас покажу.

private async void button1_Click(object sender, EventArgs e)
{
    button1.Text = await Task.Run(async delegate
    {
        string data = await DownloadAsync();
        
        // вот это будет работать, в этом смысл использования await в UI )))
        button1.Text = "как в этой точке UI-поток может получить управление?";
        
        return Compute(data);
    });
}


LR
Вот как в этой точке UI-поток может получить управление?


Давайте от обратного. Если он его там не получит, то невозможно в продолжении взаимодействовать с UI. Если UI поток не может выполнять код после await где-то внутри цепочки вызовов функций, значит невозможно будет написать сколько-нибудь серьёзный код с использованием await.
8 авг 18, 11:40    [21634062]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ВМоисеев
Member

Откуда: Редкино
Сообщений: 2006
>Petro123, сегодня, 10:57 [21634009]
>...Зачем ты это написал?
<Я так думаю.
UI поток продолжает обработку сообщений и другие методы могут осуществлять обмен. Собственно приложение ничего не ждет.
8 авг 18, 11:43    [21634065]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ВМоисеев
Member

Откуда: Редкино
Сообщений: 2006
>Petro123, сегодня, 10:57 [21634009]
>...Зачем ты это написал?
<Я так думаю.
UI поток продолжает обработку сообщений и другие методы могут осуществлять обмен. Собственно приложение ничего не ждет.
8 авг 18, 11:45    [21634071]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
Shocker.Pro
Я всегда пишу ConfigureAwait(false) кроме начальных вызовов из UI-потока, даже если и не в библиотеках.


Это нужно делать только в библиотеках, которые однозначно не взаимодействуют с UI и которым не требуется контекст синхронизации.

Shocker.Pro
Получается, что если ConfigureAwait(false) где-то забыл, то мы получим продолжение в контексте синхронизации независимо от глубины вложенности await-ов. При этом если забыли ConfigureAwait(false) на N-ом уровне вложенности, продолжение N-ого уровня выполнится в UI-потоке, и все по цепочке N-1, N-2... обратно к началу вызовов начнет выполняться в UI-потоке, потому что ConfigureAwait(false) разрешит не менять поток при продолжении. Теперь я правильно понял?


Да, глубина вложенности не имеет значения, так как компилятор строит конечный автомат.
Ну примерно, да :)

Вот хорошая заметка.

http://andrey.moveax.ru/post/csharp-async-wait-deadlocks
8 авг 18, 11:46    [21634073]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
Ещё есть такой трюк

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await AsyncHelper.RedirectToThreadPool();
    // всё, мы больше не в UI-контексте, гарантировано

    HttpClient httpClient = new HttpClient();
    string content = await httpClient.GetStringAsync("http://www.microsoft.com"); 
    // ...
}


(источник)
8 авг 18, 11:48    [21634080]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2405
hVostt
Зачем ему переходить? И почему заблуждение? Сейчас покажу.

private async void button1_Click(object sender, EventArgs e)
{
    button1.Text = await Task.Run(async delegate
    {
        string data = await DownloadAsync();
        
        // вот это будет работать, в этом смысл использования await в UI )))
        button1.Text = "как в этой точке UI-поток может получить управление?";
        
        return Compute(data);
    });
}

Это работать не будет. Будет System.InvalidOperationException: 'Cross-thread operation not valid: Control 'button1' accessed from a thread other than the thread it was created on.'

hVostt
Давайте от обратного. Если он его там не получит, то невозможно в продолжении взаимодействовать с UI. Если UI поток не может выполнять код после await где-то внутри цепочки вызовов функций, значит невозможно будет написать сколько-нибудь серьёзный код с использованием await.

Весьма странный довод.
8 авг 18, 12:04    [21634106]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 20686
hVostt
Да, глубина вложенности не имеет значения, так как компилятор строит конечный автомат.
Ну примерно, да :)
То есть, если я напишу грубо говоря
await Task.Delay(1);
Text1.Text="UI";
это будет работать, из какого бы метода это не было вызвано?
hVostt
Это нужно делать только в библиотеках, которые однозначно не взаимодействуют с UI и которым не требуется контекст синхронизации.
Ну если это код хелпера, например, внутри проекта, который не взаимодействует с UI, зачем мне его выполнять в UI?
8 авг 18, 12:05    [21634107]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
hVostt
Ещё есть такой трюк

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await AsyncHelper.RedirectToThreadPool();
    // всё, мы больше не в UI-контексте, гарантировано

    HttpClient httpClient = new HttpClient();
    string content = await httpClient.GetStringAsync("http://www.microsoft.com"); 
    // ...
}


(источник)

Чета я не допираю.
INotifyCompletion
Нафига у ThreadPoolRedirector другие члены окромя OnCompleted?
8 авг 18, 12:05    [21634108]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
ВМоисеев
>Petro123, сегодня, 10:57 [21634009]
>...Зачем ты это написал?
<Я так думаю.
UI поток продолжает обработку сообщений и другие методы могут осуществлять обмен. Собственно приложение ничего не ждет.

Не нужно додумывать за MS.
У МS термин ожидание это не form.ShowModal; из дельфи прошлого века.
Где код ГУИ встал на этой строчке.
Ожидание потока имеется ввиду.
8 авг 18, 12:14    [21634132]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
Shocker.Pro
Ну если это код хелпера, например, внутри проекта, который не взаимодействует с UI, зачем мне его выполнять в UI?


Ну может это хелпер, который может обновлять ProgressBar. Или ещё что-то делать. Серьёзные приложения имеют сложность, которая не укладывается код обработчиков событий. Код слишком большой, чтобы размещать его там, если интенсивно используются асинхронные операции. Ну и MVP/MVVM никто не отменял :)
8 авг 18, 15:20    [21634546]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
Shocker.Pro
То есть, если я напишу грубо говоря
await Task.Delay(1);
Text1.Text="UI";

это будет работать, из какого бы метода это не было вызвано?


Если в цепочке вызовов везде будет await, да.
8 авг 18, 15:21    [21634548]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 20686
hVostt
Если в цепочке вызовов везде будет await, да.
А какая разница, будет он или нет? Или ты имеешь ввиду, что код словит дедлок, потому что на Result будет заблокирован UI-поток?
8 авг 18, 15:22    [21634551]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
Shocker.Pro
hVostt
Если в цепочке вызовов везде будет await, да.
А какая разница, будет он или нет? Или ты имеешь ввиду, что код словит дедлок, потому что на Result будет заблокирован UI-поток?


В общем, LR действительно прав в том, что при вызове Task.Run текущий контекст синхронизации никак не передаётся в асинхронные вызовы внутри полученного потока для выполнения задачи. Он остаётся на точке await Task.Run.

Прошу прощения, что ввёл в заблуждение. Правда, что контекст сохраняется в цепочке вызовов на любом уровне, но не передаётся внутрь запущенных потоков.

Т.е. внутри Task.Run, ConfigureWait не влияет на выполнение.

В таком варианте, грубо:

await Some1(...)
   ...
   await Some2(...)
      ...
      await Some3(...)
         ...
         await Some4(...)
         ...
      ...
   ...


Это работает.

А теперь немного треша,

            label1.Text = await await Task.Factory.StartNew(
                async () =>
                {
                    label1.Text = "button1_Click: thinking";
                    await Task.Delay(TimeSpan.FromSeconds(3));
                    return "button1_Click: done!!";
                },
                CancellationToken.None,
                TaskCreationOptions.None,
                TaskScheduler.FromCurrentSynchronizationContext());


Два await это не ошибка :)
8 авг 18, 16:06    [21634618]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
ЕвгенийВ
Чета я не допираю.
INotifyCompletion
Нафига у ThreadPoolRedirector другие члены окромя OnCompleted?


Для await нужен объект с методом GetAwaiter
8 авг 18, 16:15    [21634643]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
Shocker.Pro
А какая разница, будет он или нет? Или ты имеешь ввиду, что код словит дедлок, потому что на Result будет заблокирован UI-поток?


По поводу вопроса, ещё раз. Если ты вызовешь Wait или Result на таске вместо await, а внутри будет await без ConfigureAwait(false) будет гарантированный дедлок.
8 авг 18, 16:16    [21634644]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ВМоисеев
Member

Откуда: Редкино
Сообщений: 2006
>Petro123, сегодня, 12:14 [url=] [21634132]
[/url]
>...Где код ГУИ встал на этой строчке…
<Стоит как миленький, и обработчики работают, и прогресс бар показывает:
object[][] psp = new object[3][];
psp[0] = new object[2] { "x_nazvanie", xstr };
psp[1] = new object[2] { "x_dt_begin", (DateTime)dpr_Начало.SelectedDate };
psp[2] = new object[2] { "x_dt_end", (DateTime)dpr_Конец.SelectedDate };
при.tmrStart(); await Task.Run(() => wsp.Entity_SP("NCUYAO_GIS.VD_Inspek_Sel", wsp.sp_Sel, psp, RowToEntity)); при.tmrStop();
8 авг 18, 16:49    [21634698]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
hVostt
ЕвгенийВ
Чета я не допираю.
INotifyCompletion
Нафига у ThreadPoolRedirector другие члены окромя OnCompleted?


Для await нужен объект с методом GetAwaiter

Т. е. для решение проблемы, о которой можно сказать, хз, есть она или нет, скорее всего нет, если механизмом async/await пользоваться только там, где он предназначен используется следующее решение -

"Используйте механизм, о котором в документации явно сказано, что это инфраструктура и нефик юзать в прикладном коде (как минимум могут изменить механизм), при чем эта инфраструктура юзает утиную типизацию. А само "решение" гарантированно подменяет пул потоков созданный специально для тасков, на пул ThreadPool существующий со времен царя Гороха."
8 авг 18, 17:25    [21634772]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ViPRos
Member

Откуда:
Сообщений: 9588
hVostt,

В сложных прогах лучше не пользоваться асинк авейт думаю - фиг концов найдешь потом
8 авг 18, 17:25    [21634774]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4831
ВМоисеев,
Открой наконец для себя возможности форматирования кода!
8 авг 18, 17:27    [21634776]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
ЕвгенийВ
Т. е. для решение проблемы, о которой можно сказать, хз, есть она или нет, скорее всего нет, если механизмом async/await пользоваться только там, где он предназначен используется следующее решение -

"Используйте механизм, о котором в документации явно сказано, что это инфраструктура и нефик юзать в прикладном коде (как минимум могут изменить механизм), при чем эта инфраструктура юзает утиную типизацию. А само "решение" гарантированно подменяет пул потоков созданный специально для тасков, на пул ThreadPool существующий со времен царя Гороха."


Ну в целом, знать как это устроено внутри полезно, но для использования нужно абстрагироваться. Нужно было бы. Если бы C# изначально проектировался с async/await, возможно получился бы простой и лёгкий синтаксис, как в Go.
8 авг 18, 18:20    [21634855]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 16062
ViPRos
hVostt,

В сложных прогах лучше не пользоваться асинк авейт думаю - фиг концов найдешь потом


Мы проект написали полностью async-first.

Из плюсов:

1. Асинхронный вызов можно встроить в любой точке на любой глубине кода.
2. Высокопроизводительное решение для обработки огромного числа запросов пользователей.

Из минусов:

1. Дофига await.
2. Дофига ConfigureAwait(false) -- помогают расширения решарпера и рослин, можно автоматизировать процесс.
3. В некоторых случаях, функциональный подход (аля промисы) -- лучше, для этого приходится оборачивать async/await (дожили).
4. Все минусы меркнут перед сложностью отладки. Нет, IDE не встанет заботливо на точку по месту ошибки. Те, кто привыкли так работать страдают и воют как кони. Но если изначально отказываться от разработки через отладку, проблем нет.
8 авг 18, 18:25    [21634863]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38643
hVostt
Мы проект написали полностью async-first.

Из плюсов:

1. Асинхронный вызов можно встроить в любой точке на любой глубине кода.

Чет ты перегнул.
Как вставить по стеку в глубине, если async не поддерживает стек?
8 авг 18, 18:38    [21634878]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 2 3 4 5 6 7 [8] 9 10 11   вперед  Ctrl      все
Все форумы / WinForms, .Net Framework Ответить