[.NET][async][WinForms]
От: nikda  
Дата: 21.12.16 08:02
Оценка:
Есть консольный проект с использованием async await.
Его вывод:

Main(1): Th= '8', TaskId= ''
fAsync(1): Th= '8', TaskId= ''
DONE
ff(1): Th= '9', TaskId= '1'
ff(2): Th= '9', TaskId= '1'
fAsync(2): Th= '9', TaskId= ''


Т.е. асинхронная операция выполняется в отдельном потоке (8). И завершается (тело метода после await) тоже в нём (9).

А в WinForms-проекте вывод такой:

Main(1): Th= '9', TaskId= ''
fAsync(1): Th= '9', TaskId= ''
ff(1): Th= '6', TaskId= '1'
DONE
ff(2): Th= '6', TaskId= '1'
fAsync(2): Th= '9', TaskId= ''


Т.е. асинхронная операция выполняется в отдельном потоке (6). А завершается (тело метода после await) в основном (9).

Как это так получается?

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main(1): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);

            fAsync();

            Console.WriteLine("DONE");
            Console.ReadKey();
        }

        private static async void fAsync()
        {
            Console.WriteLine("fAsync(1): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);

            await ff();

            Console.WriteLine("fAsync(2): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
        }

        private static Task ff()
        {
            Task t = new Task(() =>
            {
                Console.WriteLine("ff(1): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
                Thread.Sleep(5000);
                Console.WriteLine("ff(2): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
            });
            t.Start();

            return t;
        }
    }


        private void button1_Click(object sender, EventArgs e)
        {
            Debug.WriteLine("Main(1): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);

            fAsync();

            Debug.WriteLine("DONE");
        }

        private static async void fAsync()
        {
            Debug.WriteLine("fAsync(1): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);

            await ff();

            Debug.WriteLine("fAsync(2): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
        }

        private static Task ff()
        {
            Task t = new Task(() =>
            {
                Debug.WriteLine("ff(1): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
                Thread.Sleep(5000);
                Debug.WriteLine("ff(2): Th= '{0}', TaskId= '{1}'", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
            });
            t.Start();

            return t;
        }
Отредактировано 23.12.2016 3:16 VladD2 . Предыдущая версия .
Re: [.NET][async][WinForms]
От: _Raz_  
Дата: 21.12.16 08:17
Оценка: 24 (1) +2
Здравствуйте, nikda, Вы писали:

N>Как это так получается?


Эта магия называется SynchronizationContext

Parallel Computing — It's All About the SynchronizationContext
ExecutionContext vs SynchronizationContext
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.12.16 08:45
Оценка:
Здравствуйте, nikda, Вы писали:
win10 universal app, async задержка


Используй
await ff().ConfigureAwait(false); ;
и солнце б утром не вставало, когда бы не было меня
Re: [.NET][async][WinForms]
От: alexzzzz  
Дата: 21.12.16 09:58
Оценка:
Здравствуйте, nikda, Вы писали:

N>Как это так получается?


У консольных приложений отсутствует контекст синхронизации.
https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/
Re[2]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.12.16 10:08
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, nikda, Вы писали:

S>win10 universal app, async задержка


S>Используй

S>
S>await ff().ConfigureAwait(false); ;
S>


И за, что минус?
и солнце б утром не вставало, когда бы не было меня
Re[3]: [.NET][async][WinForms]
От: alexzzzz  
Дата: 21.12.16 10:21
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> И за, что минус?


ConfigureAwait ничего не даст. Без контекста синхронизации у потока нет простого способа вернуть управление в этот поток.
Отредактировано 21.12.2016 10:23 alexzzzz . Предыдущая версия .
Re[4]: [.NET][async][WinForms]
От: Lexey Россия  
Дата: 21.12.16 10:51
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>ConfigureAwait ничего не даст.


Даст. Контекст не будет использоваться.

A>Без контекста синхронизации у потока нет простого способа вернуть управление в этот поток.


А с чего ты решил, что приведенный кусок кода написан ради этого?
"Будь достоин победы" (c) 8th Wizard's rule.
Re[4]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.12.16 10:59
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>Здравствуйте, Serginio1, Вы писали:


S>> И за, что минус?


A>ConfigureAwait ничего не даст. Без контекста синхронизации у потока нет простого способа вернуть управление в этот поток.

Так у него как есть контекст синхронизации. Для WinForms это WindowsFormsSynchronizationContext

Смотри внимательно исходное сообщение

А в WinForms-проекте вывод такой:


Даже если нет Контекта синхронизации, я могу его создать


if (SynchronizationContext.Current == null)
            SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
 
        Sc = SynchronizationContext.Current;


Пример для синхронизации методов в 1С

.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия

И там я в эту ловушку попался.
По умолчанию в библиотеках нужно везде ставить .ConfigureAwait(false);

Так как по умолчанию к сожалению true. true нужно только для модификации значений контролов и можно для этого и вызывать .ConfigureAwait(true);
и солнце б утром не вставало, когда бы не было меня
Отредактировано 21.12.2016 11:10 Serginio1 . Предыдущая версия . Еще …
Отредактировано 21.12.2016 11:00 Serginio1 . Предыдущая версия .
Re[5]: [.NET][async][WinForms]
От: _Raz_  
Дата: 21.12.16 11:47
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S>По умолчанию в библиотеках нужно везде ставить .ConfigureAwait(false);

S>true нужно только для модификации значений контролов

Не нужно давать таких советов. В многопоточности и асинхронности взаимодействие с GUI отнюдь не единственная и не самая сложная задача.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[6]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.12.16 11:52
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Здравствуйте, Serginio1, Вы писали:


S>>По умолчанию в библиотеках нужно везде ставить .ConfigureAwait(false);

S>>true нужно только для модификации значений контролов

_R_>Не нужно давать таких советов. В многопоточности и асинхронности взаимодействие с GUI отнюдь не единственная и не самая сложная задача.

Угу, только вокруг этого дедлоков постоянно идут вопросы везде связанного с контекстом синхронизации.
Как раз и беда в том, что создавая библиотеку, нужно учитывать, что она может быть вызвана из контекста синхронизации.
Просто создавая библиотеку нужно везде с await добавлять .ConfigureAwait(false). И даже там, где есть контекст синхронизации, если не нужно переключаться на поток GUI.
И в чем это вредный совет?
и солнце б утром не вставало, когда бы не было меня
Отредактировано 21.12.2016 11:59 Serginio1 . Предыдущая версия .
Re[7]: [.NET][async][WinForms]
От: _Raz_  
Дата: 21.12.16 12:09
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> И в чем это вредный совет?


Люблю себя цитировать: "В многопоточности и асинхронности взаимодействие с GUI отнюдь не единственная и не самая сложная задача."
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[8]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.12.16 12:13
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Здравствуйте, Serginio1, Вы писали:


S>> И в чем это вредный совет?


_R_>Люблю себя цитировать: "В многопоточности и асинхронности взаимодействие с GUI отнюдь не единственная и не самая сложная задача."

При этом данный вопрос относится к GUI.
Еще раз в чем вредный совет про .ConfigureAwait(false)?
Учитывая, что твоя библиотека может использоваться в GUI
и солнце б утром не вставало, когда бы не было меня
Отредактировано 21.12.2016 12:15 Serginio1 . Предыдущая версия .
Re[9]: [.NET][async][WinForms]
От: TK Лес кывт.рф
Дата: 22.12.16 06:17
Оценка:
Здравствуйте, Serginio1, Вы писали:

_R_>>Люблю себя цитировать: "В многопоточности и асинхронности взаимодействие с GUI отнюдь не единственная и не самая сложная задача."

S> При этом данный вопрос относится к GUI.
S> Еще раз в чем вредный совет про .ConfigureAwait(false)?

Если есть код который может выполняться в отдельном планировщике то и запускать его там стоит явно. А вот распихивать по коду ConfigureAwait(false) в надежде так то, что оно по какой-то удаче продолжит выполняться где-то еще — решение так себе.

S> Учитывая, что твоя библиотека может использоваться в GUI


Ну это до первого Callback в GUI
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[10]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 07:13
Оценка:
Здравствуйте, TK, Вы писали:


S>> Еще раз в чем вредный совет про .ConfigureAwait(false)?


TK>Если есть код который может выполняться в отдельном планировщике то и запускать его там стоит явно. А вот распихивать по коду ConfigureAwait(false) в надежде так то, что оно по какой-то удаче продолжит выполняться где-то еще — решение так себе.


.ConfigureAwait(false) гарантирует, что будет игнорироваться Контекст синхронизации. Только и всего.



S>> Учитывая, что твоя библиотека может использоваться в GUI


TK>Ну это до первого Callback в GUI


И в чем проблема? .ConfigureAwait(false) гарантирует что будет игнорироваться Контекст синхронизации, и не будет переключаться на поток GUI.
Просто по умолчанию .ConfigureAwait(true), что приводит к дедлокам
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 9:01 Serginio1 . Предыдущая версия .
Re[3]: [.NET][async][WinForms]
От: Sinix  
Дата: 22.12.16 07:22
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S> И за, что минус?

В смысле минус? Это ж просто "не согласен" кнопка. Обозначение неудачное, но все привыкли.

Не согласен, т.к. всё советы в духе "просто используй X" без детального изучения матчасти принесут ещё больше вреда. Добавь в WPF app вот этот код:
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            RunAsync(() => button.Content = "x_X")
                .ContinueWith(t => MessageBox.Show("Completed:" + t.IsCompleted));
        }

        private async Task RunAsync(Action onNext)
        {
            await Task.Delay(1).ConfigureAwait(false);
            onNext();
        }


и попробуй найти все места, где что-то пошло не так. Там их как минимум шесть. Список —
  спойлер
по ссылке
Re[11]: [.NET][async][WinForms]
От: _Raz_  
Дата: 22.12.16 07:26
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S>Просто по умолчанию .ConfigureAwait(true), что приводит к дедлокам


Да не это приводит к дедлокам, а попытка использовать асинхронные методы в синхронном режиме.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[4]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 07:33
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Не согласен, т.к. всё советы в духе "просто используй X" без детального изучения матчасти принесут ещё больше вреда. Добавь в WPF app вот этот код:

S>
S>        private void Button_Click(object sender, RoutedEventArgs e)
S>        {
S>            RunAsync(() => button.Content = "x_X")
S>                .ContinueWith(t => MessageBox.Show("Completed:" + t.IsCompleted));
S>        }

S>        private async Task RunAsync(Action onNext)
S>        {
S>            await Task.Delay(1).ConfigureAwait(false);
S>            onNext();
S>        }
S>


S>и попробуй найти все места, где что-то пошло не так. Там их как минимум шесть. Список —

S>
  спойлер
S>по ссылке


Ны дык значения контролов нужно устанавливать в потоке GUI
Поэтому правильно делать так.

private async Task Button_Click(object sender, RoutedEventArgs e)
        {
            await RunAsync().ConfigureAwait(true);
                        button.Content = "x_X";

            MessageBox.Show("Completed:" + t.IsCompleted));
        }

А вот если в моем варианте RunAsync сделать
await Task.Delay(1);

без .
ConfigureAwait(false);

то получим дедлок
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 9:01 Serginio1 . Предыдущая версия . Еще …
Отредактировано 22.12.2016 7:39 Serginio1 . Предыдущая версия .
Отредактировано 22.12.2016 7:39 Serginio1 . Предыдущая версия .
Re[12]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 07:36
Оценка:
Здравствуйте, _Raz_, Вы писали:


S>>Просто по умолчанию .ConfigureAwait(true), что приводит к дедлокам


_R_>Да не это приводит к дедлокам, а попытка использовать асинхронные методы в синхронном режиме.


Да? Весь интернет ими усыпан. Именно для GUI по умолчанию асинхронные методы превращаются в синхронные там где это и не надо, по тому, что по умолчанию .ConfigureAwait(true).
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 9:00 Serginio1 . Предыдущая версия .
Re[5]: [.NET][async][WinForms]
От: TK Лес кывт.рф
Дата: 22.12.16 07:38
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S> Ны дык значения контролов нужно устанавливать в потоке GUI

S>Поэтому правильно делать так.

S>private async Task Button_Click(object sender, RoutedEventArgs e)

S> {
S> await RunAsync().ConfigureAwait(true);
S> button.Content = "x_X";

S> MessageBox.Show("Completed:" + t.IsCompleted));

S> }

Правильно было вообще не трогать ConfigureAwait()
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[6]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 07:42
Оценка: +1 -1
Здравствуйте, TK, Вы писали:

S>>private async Task Button_Click(object sender, RoutedEventArgs e)

S>> {
S>> await RunAsync().ConfigureAwait(true);
S>> button.Content = "x_X";

S>> MessageBox.Show("Completed:" + t.IsCompleted));

S>> }

TK>Правильно было вообще не трогать ConfigureAwait()


В данном случае да, так как ConfigureAwait(true); по умолчанию.
По мне так лучше по умолчанию использовать как раз ConfigureAwait(false); а в GUI как раз явно использовать ().ConfigureAwait(true);
там где нужно переключаться на поток GUI
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 8:40 Serginio1 . Предыдущая версия .
Re[11]: [.NET][async][WinForms]
От: TK Лес кывт.рф
Дата: 22.12.16 07:49
Оценка: +2 :)
Здравствуйте, Serginio1, Вы писали:


S> И в чем проблема? .ConfigureAwait(false) гарантирует что будет игнорироваться Контекст синхронизации, и не будет переключаться на поток GUI.

S>Просто по умолчанию .ConfigureAwait(true), что приводит к дедлокам

А false к эксепшенам? тут можно ещё предложить вынести все эти true/false в конфиг. А конфиг генерить самообучающейся сетью которая по дедлокам/эксепшенам/сигнатурам методов будет предлагать правильные значения

Плюс для тестеров апгрейд — раньше они просто тестировали, а теперь будут фактически воспитывать.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[5]: [.NET][async][WinForms]
От: Sinix  
Дата: 22.12.16 07:55
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Поэтому правильно делать так.

Неправильно делать так.

.ConfigureAwait(true) приводит к вызову
            public void OnCompleted(Action continuation)
            {
                TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true);
            }

обычный await заканчивается тем же.

Таки советую сначала изучить матчасть, а затем уже рассуждать про правильно/неправильно. Порядок важен

P.S. Поправь оверквотинг в ответах. Читать же неудобно
Re[13]: [.NET][async][WinForms]
От: _Raz_  
Дата: 22.12.16 07:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Да? Весь интернет ими усыпан.


Благодаря советам в форме категорического императива

S> Именно для GUI по умолчанию асинхронные методы превращаются в синхронные там где это и не надо, по тому, что по умолчанию .ConfigureAwait(true).


Очень показательное слово выбрал — "превращаются". Магия, да? И взмах волшебной палочки в виде ConfigureAwait нам поможет. Ну что-ж, удачи в лечении симтомов, а не болезни.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[12]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 08:29
Оценка:
Здравствуйте, TK, Вы писали:
TK>А false к эксепшенам? тут можно ещё предложить вынести все эти true/false в конфиг. А конфиг генерить самообучающейся сетью которая по дедлокам/эксепшенам/сигнатурам методов будет предлагать правильные значения

TK>Плюс для тестеров апгрейд — раньше они просто тестировали, а теперь будут фактически воспитывать.


Ну то есть везде в библиотеках лепить ConfigureAwait(false), на случай вызова из GUI это нормально?
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 9:00 Serginio1 . Предыдущая версия .
Re[6]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 08:32
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>Поэтому правильно делать так.

S>Неправильно делать так.

S>.ConfigureAwait(true) приводит к вызову

S>
S>            public void OnCompleted(Action continuation)
S>            {
S>                TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true);
S>            }
S>

S>обычный await заканчивается тем же.

S>Таки советую сначала изучить матчасть, а затем уже рассуждать про правильно/неправильно. Порядок важен

Угу ты бы хоть раз прочитал, что я пушу. Я как раз и пишу, что по умолчанию ConfigureAwait(true), а нужно наоборот, что бы возвращаться в поток GUI тогда когда это нужно для установки значений контролов.

Просто когда пишешь код для xamarin, WPF , 1C нужно учитывать этот контекст синхронизации там где он есть и там где его нет писать ConfigureAwait(false).
S>P.S. Поправь оверквотинг в ответах. Читать же неудобно

Я знаю. Именно пишу ConfigureAwait(true), что по уму нужно по умолчанию как раз ConfigureAwait(false), а ConfigureAwait(true) там, где нужно реально переключаться на поток GUI/
И всем кто пишет в GUI это будет понятно. А так любой await по умолчанию нужно это или не нужно переключается на поток GUI/
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 8:39 Serginio1 . Предыдущая версия .
Re[14]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 08:35
Оценка:
Здравствуйте, _Raz_, Вы писали:


S>> Именно для GUI по умолчанию асинхронные методы превращаются в синхронные там где это и не надо, по тому, что по умолчанию .ConfigureAwait(true).


_R_>Очень показательное слово выбрал — "превращаются". Магия, да? И взмах волшебной палочки в виде ConfigureAwait нам поможет. Ну что-ж, удачи в лечении симтомов, а не болезни.

Болезнь как раз в том, что await по умолчанию .ConfigureAwait(true) когда возвращается в поток GUI где надо и где не надо.
А программист это волшебник. Ты разве не знал?
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 8:59 Serginio1 . Предыдущая версия .
Re[7]: [.NET][async][WinForms]
От: Sinix  
Дата: 22.12.16 08:48
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Я знаю. Именно пишу ConfigureAwait(true), что по уму нужно по умолчанию как раз ConfigureAwait(false), а ConfigureAwait(true) там, где нужно реально переключаться на поток GUI/

Первое правило любого предложения в стиле "а давайте сделаем так": посмотри на последствия.

Сейчас await task.ConfigureAwait(true); идентичен по поведению простому await task;. Это решение абсолютно правильно, т.к поведение заточено под конечных пользователей.
В твоём варианте большинство клиентского кода или содержало бы баги, или было бы отравлено копипастой с .ConfigureAwait. Это очень плохое решение, поэтому в фреймворк оно не прошло.


P.S. Напоминаю:
S>>P.S. Поправь оверквотинг в ответах. Читать же неудобно

Капсом писать что ли?
(rsdn позволяет редактировать ответы, если что).
Re[8]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 08:59
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> Я знаю. Именно пишу ConfigureAwait(true), что по уму нужно по умолчанию как раз ConfigureAwait(false), а ConfigureAwait(true) там, где нужно реально переключаться на поток GUI/

S>Первое правило любого предложения в стиле "а давайте сделаем так": посмотри на последствия.

Я как раз и смотрю и вижу косяки. При этом никто не знает про ConfigureAwait
S>Сейчас await task.ConfigureAwait(true); идентичен по поведению простому await task;. Это решение абсолютно правильно, т.к поведение заточено под конечных пользователей.
S>В твоём варианте большинство клиентского кода или содержало бы баги, или было бы отравлено копипастой с .ConfigureAwait. Это очень плохое решение, поэтому в фреймворк оно не прошло.

Большинство клиентского кода как раз потому, что сделали ConfigureAwait(true) по умолчанию и никто не знает про существование ConfigureAwait. И весь интернет усыпан вопросами о дедлоках.
При этом не везде в клиентском коде нужно переключатся на поток контекста.
При этом в ошибки установки свойств контрола в не потоке GUI можно возвращать ошибку про использовании ConfigureAwait, а с дедлоком вообще ничего не выдается.

S>P.S. Напоминаю:

S>>>P.S. Поправь оверквотинг в ответах. Читать же неудобно

S>Капсом писать что ли?

S>(rsdn позволяет редактировать ответы, если что).

Правлю.
и солнце б утром не вставало, когда бы не было меня
Re[13]: [.NET][async][WinForms]
От: TK Лес кывт.рф
Дата: 22.12.16 09:05
Оценка:
Здравствуйте, Serginio1, Вы писали:

TK>>Плюс для тестеров апгрейд — раньше они просто тестировали, а теперь будут фактически воспитывать.

S> Ну то есть везде в библиотеках лепить ConfigureAwait(false), на случай вызова из GUI это нормально?

Главное, это настройки в конфиг вынести. А дальше, можно просто по подстроке — если метод содержит click то, по умолчанию true, а если run то false. Ну или наоборот
Можно и рандомом раскидать — опытный тестер / конфигуратор / воспитатель сам все настроит как считает нужным.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[14]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 09:17
Оценка:
Здравствуйте, TK, Вы писали:

TK>Здравствуйте, Serginio1, Вы писали:


TK>>>Плюс для тестеров апгрейд — раньше они просто тестировали, а теперь будут фактически воспитывать.

S>> Ну то есть везде в библиотеках лепить ConfigureAwait(false), на случай вызова из GUI это нормально?

TK>Главное, это настройки в конфиг вынести. А дальше, можно просто по подстроке — если метод содержит click то, по умолчанию true, а если run то false. Ну или наоборот

TK>Можно и рандомом раскидать — опытный тестер / конфигуратор / воспитатель сам все настроит как считает нужным.
Кстати а можно указать для компилятора, что по умолчанию ConfigureAwait(false)?
Просто для библиотек это было бы удобно.
и солнце б утром не вставало, когда бы не было меня
Re[9]: [.NET][async][WinForms]
От: Sinix  
Дата: 22.12.16 09:32
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>Первое правило любого предложения в стиле "а давайте сделаем так": посмотри на последствия.

S> Я как раз и смотрю и вижу косяки.
Не вопрос, какие именно косяки?


S> Большинство клиентского кода как раз потому, что сделали ConfigureAwait(true) по умолчанию и никто не знает про существование ConfigureAwait. И весь интернет усыпан вопросами о дедлоках.

А можно пример? Есть такое подозрение, что проблема там не в ConfigureAwait(), а в исчерпании потоков, доступных для запуска продолжений. Так это и с ConfigureAwait(false) можно устроить, дурное дело нехитрое


S>При этом не везде в клиентском коде нужно переключатся на поток контекста.

По умолчанию — везде. Если, конечно, не хочется ловить баги типа "опс, культура не та" в самом неожиданном месте.

S> При этом в ошибки установки свойств контрола в не потоке GUI можно возвращать ошибку про использовании ConfigureAwait, а с дедлоком вообще ничего не выдается.

Не вопрос, давай с всё тем же кодом из примера выше. Есть идеи, как заставить его выдавать ошибку стандартными средствами фреймворка? Не ломая совместимости.
Напоминаю, исключение по факту бросается в фоновом потоке.

И после этого — как быть с ошибками, не связанными с обращением к UI?

S> Правлю.

Спасиб
Re[10]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 10:16
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>Первое правило любого предложения в стиле "а давайте сделаем так": посмотри на последствия.

S>> Я как раз и смотрю и вижу косяки.
S>Не вопрос, какие именно косяки?
Да постоянные вопросы из-за дедлоков

S>> Большинство клиентского кода как раз потому, что сделали ConfigureAwait(true) по умолчанию и никто не знает про существование ConfigureAwait. И весь интернет усыпан вопросами о дедлоках.

S>А можно пример? Есть такое подозрение, что проблема там не в ConfigureAwait(), а в исчерпании потоков, доступных для запуска продолжений. Так это и с ConfigureAwait(false) можно устроить, дурное дело нехитрое
Так я тебе в твоем примере и привел, когда при вызове RunAsync внутри ты будешь не будешь использовать ConfigureAwait(false)
Просто ты не читаешь.

private async Task Button_Click(object sender, RoutedEventArgs e)
        {
            await RunAsync().Wait(); //1
            button.Content = "x_X";

            MessageBox.Show("Completed:" + t.IsCompleted));
        }

private async Task RunAsync()
      {
            await Task.Delay(1); //2 Получим классический дедлок
// Так как  await Task.Delay(1); возвращается в поток GUI но, await RunAsync() его ждет
 

        }


Мало того ты же минус мне влепил за http://ru.stackoverflow.com/questions/512968/win10-universal-app-async-%d0%b7%d0%b0%d0%b4%d0%b5%d1%80%d0%b6%d0%ba%d0%b0/513241#513241

Клик по кнопке здесь приводит к дедлоку. UI поток стартует новый I/O поток на строке «2» и уходит в спящий режим на строке «1», ожидая завершения работы. После того как I/O поток заканчивает выполнение, оставшаяся часть метода RunAsync передается на выполнение вызывающему (UI) потоку. Но тот в это время находится в спящем режиме, ожидая завершения метода. Дедлок.



S>>При этом не везде в клиентском коде нужно переключатся на поток контекста.

S>По умолчанию — везде. Если, конечно, не хочется ловить баги типа "опс, культура не та" в самом неожиданном месте.

Вот именно. Но это бывает не всегда. А народ про ().ConfigureAwait(false); вообще не знает

S>> При этом в ошибки установки свойств контрола в не потоке GUI можно возвращать ошибку про использовании ConfigureAwait, а с дедлоком вообще ничего не выдается.

S>Не вопрос, давай с всё тем же кодом из примера выше. Есть идеи, как заставить его выдавать ошибку стандартными средствами фреймворка? Не ломая совместимости.
S>Напоминаю, исключение по факту бросается в фоновом потоке.

Не ломая совместимости можно для библиотек сделать опцию для компилятора или проекта ConfigureAwait(false) по умолчанию.
S>И после этого — как быть с ошибками, не связанными с обращением к UI?
А все также и остается. Но проблема дедлоков и лишней писанины убирается.
S>> Правлю.
S>Спасиб

Все посыпаю голову пеплом! Что то я совсем заработался. Проблема с Result.
Я в 1С не могу вызвать await поэтому мне приходится вызывать Result, а он как раз и ведет к дедлоку.
У всех прошу прощения и удаляюсь в монастырь.
Но вот сделать опцию для ConfigureAwait(false); стоит
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 10:21 Serginio1 . Предыдущая версия .
Re[11]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 10:19
Оценка:
Все посыпаю голову пеплом! Что то я совсем заработался. Проблема с Result.
Я в 1С не могу вызвать await поэтому мне приходится вызывать Result, а он как раз и ведет к дедлоку.
А вызывать через события муторно.
У всех прошу прощения и удаляюсь в монастырь.
Но вот сделать опцию для ConfigureAwait(false); стоит
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 10:51 Serginio1 . Предыдущая версия . Еще …
Отредактировано 22.12.2016 10:20 Serginio1 . Предыдущая версия .
Re[11]: [.NET][async][WinForms]
От: Sinix  
Дата: 22.12.16 11:44
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Так я тебе в твоем примере и привел, когда при вызове RunAsync внутри ты будешь не будешь использовать ConfigureAwait(false)

S>Просто ты не читаешь.

Скорее наоборот Цитато:

проблема там не в ConfigureAwait(), а в исчерпании потоков, доступных для запуска продолжений

Код await RunAsync().Wait(); именно это и делает — блокирует все доступные потоки (их одна штука). Вот тебе другой пример того же поведения:
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(8, 8);
            // ...
            RunAsync(10).Wait();
            Console.WriteLine(total);
        }

        private static volatile int total = 0;

        private static async Task RunAsync(int i)
        {
            if (i == 0)
                return;

            Console.WriteLine(i);
            await Task.Delay(1).ConfigureAwait(false);
            RunAsync(i - 1).Wait();
            Interlocked.Increment(ref total);
        }
    }
}


Ну как, помог ConfigureAwait(false)?

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



S> Мало того ты же минус мне влепил за http://ru.stackoverflow.com/questions/512968/win10-universal-app-async-%d0%b7%d0%b0%d0%b4%d0%b5%d1%80%d0%b6%d0%ba%d0%b0/513241#513241


Вот дался тебе тот минус? Это ж не способ оценить автора, это намёк на "с сообщением не согласен, но расписывать лень". Может правда лень, может аргументов просто нет, не надо на это обращать внимания. Убрал, тем более что сигнал уже дошёл

Если про минус на ru.stackoverflow.com, то ты точно меня с кем-то перепутал. Я на русскоязычном вообще не отмечаюсь, да и на основном отвечаю очень редко.

S> Вот именно. Но это бывает не всегда. А народ про ().ConfigureAwait(false); вообще не знает

И оно отлично работает, если самому не раскладывать грабли. Причём это можно сделать кучей способов, от которых ConfigureAwait не спасёт, пример выше. Ну а после наступания народ сразу познаёт дао и больше так не делает. Куда не погляди — везде плюсы
Re[12]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 13:19
Оценка:
Здравствуйте, Sinix, Вы писали:


S>> Вот именно. Но это бывает не всегда. А народ про ().ConfigureAwait(false); вообще не знает

S>И оно отлично работает, если самому не раскладывать грабли. Причём это можно сделать кучей способов, от которых ConfigureAwait не спасёт, пример выше. Ну а после наступания народ сразу познаёт дао и больше так не делает. Куда не погляди — везде плюсы
Ну я уже извинился. Но даже при этом считаю, что нужна опция для ConfigureAwait(false); для библиотек. Например в 1С я не могу использовать await.
И во многих случаях переключать контекст не стоит, но из-за того, что ConfigureAwait(true); просто мы теряем в производительности на переключение потока и ожидание когда основной поток GUI освободится, там где нам не нужно использовать контролы.
и солнце б утром не вставало, когда бы не было меня
Re[13]: [.NET][async][WinForms]
От: Sinix  
Дата: 22.12.16 13:28
Оценка: 18 (2)
Здравствуйте, Serginio1, Вы писали:

S> Но даже при этом считаю, что нужна опция для ConfigureAwait(false); для библиотек.

Вот тут объяснение и обходной путь есть
http://stackoverflow.com/questions/23713344/set-configureawaitfalse-for-entire-project-dll

И по исходному вопросу попалось —
http://stackoverflow.com/questions/26681332/why-configureawaitfalse-is-not-the-default-option
Re[14]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.12.16 13:45
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> Но даже при этом считаю, что нужна опция для ConfigureAwait(false); для библиотек.

S>Вот тут объяснение и обходной путь есть
S>http://stackoverflow.com/questions/23713344/set-configureawaitfalse-for-entire-project-dll
Огромное спасибо! У Fody много вкусностей.
https://github.com/Fody/Fody/
https://habrahabr.ru/company/microsoft/blog/304678/

Кстати AsyncErrorHandler

S>И по исходному вопросу попалось —

S>http://stackoverflow.com/questions/26681332/why-configureawaitfalse-is-not-the-default-option
Это все понятно. Еще раз огромное спасибо за Fody Нужно его повнимательнее изучить.
Кстати тут статья пробегала про возможные нововведения https://habrahabr.ru/post/312048/
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.12.2016 14:16 Serginio1 . Предыдущая версия .
Re[12]: [.NET][async][WinForms]
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.12.16 19:39
Оценка: +1 :)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> Так я тебе в твоем примере и привел, когда при вызове RunAsync внутри ты будешь не будешь использовать ConfigureAwait(false)

S>>Просто ты не читаешь.

S>Скорее наоборот Цитато:

S>

S>проблема там не в ConfigureAwait(), а в исчерпании потоков, доступных для запуска продолжений

S>Код await RunAsync().Wait(); именно это и делает — блокирует все доступные потоки (их одна штука). Вот тебе другой пример того же поведения:

Еще раз. Я в 1С использую Контекст Синхронизации для получения ком событий в потоке GUI 1c.
S>
S>using System;
S>using System.Threading;
S>using System.Threading.Tasks;

S>namespace ConsoleApp3
S>{
S>    class Program
S>    {
S>        static void Main(string[] args)
S>        {
S>            ThreadPool.SetMinThreads(1, 1);
S>            ThreadPool.SetMaxThreads(8, 8);
S>            // ...
S>            RunAsync(10).Wait();
S>            Console.WriteLine(total);
S>        }

S>        private static volatile int total = 0;

S>        private static async Task RunAsync(int i)
S>        {
S>            if (i == 0)
S>                return;

S>            Console.WriteLine(i);
S>            await Task.Delay(1).ConfigureAwait(false);
S>            RunAsync(i - 1).Wait();
S>            Interlocked.Increment(ref total);
S>        }
S>    }
S>}
S>


S>Ну как, помог ConfigureAwait(false)?


Вот такого выделенного я в 1С не могу сделать, а в вот вместо выделенного в библиотеке
await RunAsync(i - 1).Wait;


await RunAsync(i — 1) легко
S>Надеюсь, теперь понятно, про что уже четыре человека в топике пытаются тебе намекнуть: не надо лечить симптомы, не разобравшись с болезнью.

Я уже 1000+1 раз объяснил свою проблему в 1С. Но Вы не слушаете. Огромное спасибо за ConfigureAwait.Fody
Еще раз не везде можно использовать await, но можно использовать WindowsFormsSynchronizationContext и для получения результата использовать методы синхронизации.
Мне это нужно, а вам нет. Но это не значит, что проблемы не существует.

Еще раз дам ссылочки

.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия

А вот при использовании напрbмер HTTPClient можно использовать синхронные методы потому, что в библиотеке все методы .ConfigureAwait(false);

Но вот могут попасться и библиотек ConfigureAwait по умолчанию.

Использовать асинхронные методы можно, но это не всегда удобно.

Асинхронное программирование в 1С через использование классов .Net из Native ВК

Поэтому, если у Вас не болит, то это не значит, что не болит у всех

Да и в GUI далеко не всегда нужно переключаться на поток GUI. Раньше до await использовали Invoke
delegate void AddTextToTListBox(string text);

        void msg_OnSendChatMessage(string message)
        {
            
            if (listBox1.InvokeRequired)
            {
                AddTextToTextBox d = new AddTextToTextBox(msg_OnSendChatMessage);
                this.Invoke(d, new object[] { message });
            }
            else
            {
                listBox1.Text += message + "\r\n";
            }  
        }


И это было нормально. А вот ConfigureAwait(true) это уже извращение.

Еще раз огромное спасибо за ConfigureAwait.Fody. Это решение всех моих проблем.
Но к сожалению, не решает проблем со сторонними библиотеками где не используют .ConfigureAwait(false);
и солнце б утром не вставало, когда бы не было меня
Отредактировано 25.12.2016 17:43 Serginio1 . Предыдущая версия . Еще …
Отредактировано 25.12.2016 17:35 Serginio1 . Предыдущая версия .
Отредактировано 24.12.2016 20:02 Serginio1 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.