powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / От чего может виснуть этот код?
25 сообщений из 44, страница 1 из 2
От чего может виснуть этот код?
    #40060522
Примерно так:

В form_Load:

Код: c#
1.
2.
3.
4.
5.
6.
new Task(async () =>
{
  await LoadSomeEntities1().ConfigureAwait(false);
  await LoadSomeEntities2().ConfigureAwait(false);
  await LoadSomeEntities3().ConfigureAwait(false);
}).RunSynchronously();



Форма загружается, всё отрабатывает, всё загружено. Никаких проблем!

В combobox_selectedIndexChanged:

Код: c#
1.
LoadSomeEntities3().ConfigureAwait(false).GetAwaiter().GetResult();



А в самой функции:

Код: 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.
async Task LoadSomeEntities3()
{
  trvTreeView.SuspendLayout();
  trvTreeView.BeginUpdate();
  trvTreeView.Nodes.Clear();

  await ReadEntitesFromDB().ConfigureAwait(false); // Но если здесь убрать await и добавить .GetAwaiter().GetResult(), то не виснет
  foreach(var entity in entities)
  {
    if(trvTreeView.InvokeRequired)
    {
      trvTreeView.Invoke((MethodDelegate) delegate // виснет здесь только при выборе значения в комбобоксе
      {
        trvTreeView.Nodes.Add(entity.Name);
      });
    }
    else
    {
       trvTreeView.Nodes.Add(entity.Name);
    }
  }

  if(trvTreeView.InvokeRequired)
  {
    trvTreeView.Invoke((MethodDelegate) delegate 
    {
      trvTreeView.EndUpdate();
      trvTreeView.ResumeLayout();
    }
  }
  else
  {
    trvTreeView.EndUpdate();
    trvTreeView.ResumeLayout();
  }
}



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

В обоих случаях InvokeRequired = true, соответственно всегда отрабатывает делегат.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060529
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство
Код: c#
1.
await ReadEntitesFromDB().ConfigureAwait(false); // Но если здесь убрать await и добавить .GetAwaiter().GetResult(), то не виснет



потому что так делать нельзя, объяснять долго, нудно, всё это можно найти и почитать в документации.

непонятно зачем так делаете, это просто эксперименты?

https://stackoverflow.com/questions/5095183/how-would-i-run-an-async-taskt-method-synchronously
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060540
что значит нельзя? так делают все и везде. в чём конкретно претензия?
и зачем мне ссылка на синхронное исполнение асинхронного вызова? синхронно-то оно и так работает.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060548
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство
что значит нельзя?


то и значит.

Бариску Нацарство
так делают все и везде. в чём конкретно претензия?


Код: c#
1.
2.
3.
4.
5.
6.
new Task(async () =>
{
  await LoadSomeEntities1().ConfigureAwait(false);
  await LoadSomeEntities2().ConfigureAwait(false);
  await LoadSomeEntities3().ConfigureAwait(false);
}).RunSynchronously();



так даже в дремучем колхозе делать моветон.


Бариску Нацарство
и зачем мне ссылка на синхронное исполнение асинхронного вызова? синхронно-то оно и так работает.


у вас асинхронный метод

Код: c#
1.
async Task LoadSomeEntities3()



зачем вы в этом методе асинхронный метод пытаетесь вызвать "синхронно"?

Код: c#
1.
await ReadEntitesFromDB().ConfigureAwait(false); // Но если здесь убрать await и добавить .GetAwaiter().GetResult(), то не виснет



зачем убирать await и добавлять GetResult()? это во-первых неправильно, что как бы подтверждается тем, что "виснет", во-вторых.. зачем? это для чего?
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060549
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство,

и зачем вы везде .ConfigureAwait(false) добавляете? при чём там, где как раз этого делать нельзя.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060553
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство,

Код: c#
1.
2.
3.
4.
5.
6.
private async void Form1_LoadAsync(object sender, EventArgs e)
{
    await LoadSomeEntities1().ConfigureAwait(false);
    await LoadSomeEntities2().ConfigureAwait(false);
    await LoadSomeEntities3().ConfigureAwait(false);
}


Не нужно их оборачивать в Task и запускать синхронно.
При желании, можно написать так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
private async void Form1_LoadAsync(object sender, EventArgs e)
{
    var t1 = LoadSomeEntities1();
    var t2 = LoadSomeEntities2();
    var t3 = LoadSomeEntities3();
    await Task.WhenAll(t1, t2, t3);
}


Так все три метода будут выполняться одновременно, то есть общее выполнение будет быстрее. Но это если они не обращаются к одним и тем же объектам.


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
async Task LoadSomeEntities1()
{
    trvTreeView.SuspendLayout();
    trvTreeView.BeginUpdate();
    trvTreeView.Nodes.Clear();

    // Возвращаемся в тот же контекст синхронизации,
    // поэтому вызовы Invoke не нужны.
    await ReadEntitesFromDB();

    foreach (var entity in entities)
    {
        trvTreeView.Nodes.Add(entity.Name);
    }

    trvTreeView.EndUpdate();
    trvTreeView.ResumeLayout();
}


И это всё! Суть и красота асинхронности заключена в лаконичности, которую она позволяет.


Код: c#
1.
2.
3.
4.
private async void ComboBox_SelectedIndexChangedAsync(object sender, EventArgs e)
{
    await LoadSomeEntities3();            
}



Ничего не виснет, всё летает!

ЗЫ: у обработчиков событий в сигнатуре должно быть async.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060562
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvik
ЗЫ: у обработчиков событий в сигнатуре должно быть async.


да, void async-и поддержали только ради событий WinForms
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060743
Джон Скит из МС утверждает везде что на каждом асинхронном вызове должен висеть .ConfigureAwait(false).
Вы утверждаете, что это делает вызов синхронным. И кому верить?

> зачем убирать await и добавлять GetResult()? это во-первых неправильно, что как бы подтверждается тем, что "виснет", во-вторых.. зачем? это для чего?

чтобы не висло. Вы, кажется, всё перепутали: как "неправильно" не виснет. Как сейчас виснет.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060764
petalvik
Бариску Нацарство,
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
async Task LoadSomeEntities1()
{
    trvTreeView.SuspendLayout();
    trvTreeView.BeginUpdate();
    trvTreeView.Nodes.Clear();

    // Возвращаемся в тот же контекст синхронизации,
    // поэтому вызовы Invoke не нужны.
    await ReadEntitesFromDB();

    foreach (var entity in entities)
    {
        trvTreeView.Nodes.Add(entity.Name);
    }

    trvTreeView.EndUpdate();
    trvTreeView.ResumeLayout();
}


И это всё! Суть и красота асинхронности заключена в лаконичности, которую она позволяет.

ЗЫ: у обработчиков событий в сигнатуре должно быть async.


Сделал всё, как Вы советуете выше. Вроде бы всё работает, только две проблемы остались:

await ReadEntitesFromDB(); виснет, если не добавить .ConfigureAwait(false)

и всё-таки добавление нод в trvTreeView по-прежнему бросает исключение об обращении из другой нити, если не оставить .Invoke((MethodDelegate)
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060773
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство,

Вот этот код ошибочен:

Код: c#
1.
2.
3.
4.
5.
6.
private async void Form1_LoadAsync(object sender, EventArgs e)
{
    await LoadSomeEntities1().ConfigureAwait(false);
    await LoadSomeEntities2().ConfigureAwait(false);
    await LoadSomeEntities3().ConfigureAwait(false);
}


Здесь нужно убрать .ConfigureAwait(false). Потому что в этих методах происходит обращение к GUI-контролам.
Правильный код:

Код: c#
1.
2.
3.
4.
5.
6.
private async void Form1_LoadAsync(object sender, EventArgs e)
{
    await LoadSomeEntities1();
    await LoadSomeEntities2();
    await LoadSomeEntities3();
}



Теперь не будет бросать исключение.


Бариску Нацарство

await ReadEntitesFromDB(); виснет, если не добавить .ConfigureAwait(false)

Значит код в методе ReadEntitesFromDB() написан неправильно. Наверняка там тоже присобачено .GetAwaiter().GetResult() или что-то ещё. Покажи код.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060774
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство,

И ещё. Вызовы trvTreeView.SuspendLayout(); и trvTreeView.ResumeLayout(); не нужны. Если, конечно, в тривью не добавляются дочерние контролы вызовом trvTreeView.Controls.Add(...);
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060851
petalvik
Бариску Нацарство,

Вот этот код ошибочен:


Спасибо, всё почистил, всё работает.
Объяснил бы ещё кто зачем тот самый Джон Скит везде пугает не использовать async void и настаивает чтобы на каждом await висел .ConfigureAwait(false). Я поначалу делал именно как Вы советуете, но меня затроллили и много лет заставляли добавлять .ConfigureAwait(false).
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060857
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство
Объяснил бы ещё кто зачем тот самый Джон Скит везде пугает не использовать async void и настаивает чтобы на каждом await висел .ConfigureAwait(false). Я поначалу делал именно как Вы советуете, но меня затроллили и много лет заставляли добавлять .ConfigureAwait(false).
А не проще ли взять учебник и прочесть, что делает ConfigureAwait(false) и что такое контекст синхронизации и поток пользовательского интерфейса. Не перепечатывать же учебник на форум.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060877
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
да, void async-и поддержали только ради событий WinForms

Почему это? События есть не только в винформс, а много ещё где - в т.ч. в областях, вообще никак не связанных с GUI:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
var timer = new System.Timers.Timer(TimeSpan.FromSeconds(1).TotalMilliseconds)
{
  AutoReset = true,
  Enabled = false
};
timer.Elapsed += TimerElapsed;
timer.Start();
...
static async void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
  await Task.Delay(TimeSpan.FromSeconds(1));
  Console.WriteLine("Tick: {0}", DateTime.Now);
}
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060905
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТС ссылку-то не дал, а Джон Скит наверняка имел ввиду - не плодить собственные сигнатуры с async void. А от легаси никуда не денешься, потому это исключение. Да и про ConfugureAwait наверняка указывал те случаи, когда его нельзя применять. Но зачем вникать в детали - давай везде пихать.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060922
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство
Джон Скит из МС утверждает везде что на каждом асинхронном вызове должен висеть .ConfigureAwait(false).
Вы утверждаете, что это делает вызов синхронным. И кому верить?


ничего он такого не утверждает.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060923
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны
Почему это? События есть не только в винформс, а много ещё где - в т.ч. в областях, вообще никак не связанных с GUI:


за пределами WinForms события лучше не использовать.
и вообще забыть про них как про страшный сон.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060928
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro
ТС ссылку-то не дал, а Джон Скит наверняка имел ввиду - не плодить собственные сигнатуры с async void.

Об этом пишет не только Скит (который, кстати говоря, давно уже в гугле работает). Вот, например: https://docs.microsoft.com/en-us/archive/blogs/ptorr/async-exceptions-in-c
Причина достаточно банальна: void не содержит информации о контексте выполнения задачи, т.к. это void. И поэтому с void есть вот такое:
Код: 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.
static async Task Main()
{
  AppDomain.CurrentDomain.UnhandledException += (s, e)
    => Console.WriteLine("UnhandledException: {0}", e.ExceptionObject);
  TaskScheduler.UnobservedTaskException += (s, e) =>
    Console.WriteLine("UnobservedTaskException: {0}", e);
  Console.WriteLine("Running TestTask");
  try
  {
    await TestTask();
  }
  catch (Exception e)
  {
    Console.WriteLine("TestTask error: {0}", e);
  }
  Console.WriteLine("Running TestVoid");
  try
  {
    TestVoid(); // здесь await использовать нельзя
  }
  catch (Exception e)
  {
    Console.WriteLine("TestVoid error: {0}", e);
  }
  Console.WriteLine("done");
}

static async void TestVoid()
{
  await Task.Yield();
  throw new ApplicationException("TestVoid");
}

static async Task TestTask()
{
  await Task.Yield();
  throw new ApplicationException("TestVoid");
}


Код: plaintext
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.
Running TestTask
TestTask error: System.ApplicationException: TestVoid
   at test2.Program.<TestTask>d__2.MoveNext() in D:\Projects\.Net\_tests\test2\test2\Program.cs:line 54
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at test2.Program.<Main>d__0.MoveNext() in D:\Projects\.Net\_tests\test2\test2\Program.cs:line 26
Running TestVoid
done
UnhandledException: System.ApplicationException: TestVoid
   at test2.Program.<TestVoid>d__1.MoveNext() in D:\Projects\.Net\_tests\test2\test2\Program.cs:line 48
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback,
        Object state, Boolean preserveSyncCtx
)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback,
       Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

Unhandled Exception: System.ApplicationException: TestVoid
   at test2.Program.<TestVoid>d__1.MoveNext() in D:\Projects\.Net\_tests\test2\test2\Program.cs:line 48
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback,
       Object state, Boolean preserveSyncCtx
)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback,
      Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060931
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
за пределами WinForms события лучше не использовать.
и вообще забыть про них как про страшный сон.

Интересно, как это можно реализовать, например, в случае SqlConnection.InfoMessage (таких примеров можно привести много)
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40060938
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны
Интересно, как это можно реализовать, например, в случае SqlConnection.InfoMessage (таких примеров можно привести много)


Согласен, есть легаси контракты, которые до сих пор поддерживаются.
От этих эвентов нужно максимально абстрагироваться и декорировать.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40061016
hVostt
Бариску Нацарство
Джон Скит из МС утверждает везде что на каждом асинхронном вызове должен висеть .ConfigureAwait(false).
Вы утверждаете, что это делает вызов синхронным. И кому верить?


ничего он такого не утверждает.


Он именно так и утверждает в каждом из его 1000ч постов, которые он плодит на стэкэксчендже и в каждом ссылается на свои блог посты. Везде одно и то же: вешайте .ConfigureAwait(false) на каждый await чтобы не было дедлоков.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40061020
Shocker.Pro
А не проще ли взять учебник и прочесть

А какой учебник?

Я 5 лет работал в компании, где, в соответствии утверждениям Скита, .ConfigureAwait(false) висел на каждом await, и мои пулл реквесты не одобряли, пока я не добавлял их. Объяснить, зачем они это требуют, правда тоже не могли.
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40061036
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бариску Нацарство
Везде одно и то же: вешайте .ConfigureAwait(false) на каждый await чтобы не было дедлоков.

Блин, а просто самому прочтитать доки о том, что делает .ConfigureAwait(...) сложно, что ли?
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40061118
fkthat
Бариску Нацарство
Везде одно и то же: вешайте .ConfigureAwait(false) на каждый await чтобы не было дедлоков.

Блин, а просто самому прочтитать доки о том, что делает .ConfigureAwait(...) сложно, что ли?


Configures the awaiter to await this Task<TResult>.

true to attempt to marshal the continuation back to the original context captured; otherwise, false.

И что это мне должно сказать?
...
Рейтинг: 0 / 0
От чего может виснуть этот код?
    #40061138
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
25 сообщений из 44, страница 1 из 2
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / От чего может виснуть этот код?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]