#c# #wpf #asynchronous #async-await #dispatcher
#c# #wpf #асинхронный #асинхронное ожидание #диспетчер
Вопрос:
У меня есть метод загрузки, который выполняется асинхронно. Внутри этого метода я изменяю Проверенное состояние радиокнопки.
Это работает нормально, и не имеет значения, выполняю ли я его напрямую или через диспетчер.BeginInvoke .
Однако у RadioButton есть событие «CheckedChanged». Когда я вызываю
Dispatcher.Invole((Action)()=>{rb.IsChecked=true;}));
Я бы ожидал, что мой асинхронный метод будет ждать выполнения события checked changed (которое снова запускает асинхронный метод).
В прилагаемом коде вы увидите, что порядок выполнения:
- «BeginInvoke»
- «EndInvoke»
- «RbChanged»
То, что я хотел бы иметь, это:
- «BeginInvoke»
- «RbChanged»
- «EndInvoke»
Какие-либо варианты для этого?
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
}
private async enter code herevoid Window_Loaded(object sender, RoutedEventArgs e)
{
await RightAfterLoading();
}
private async Task RightAfterLoading()
{
Debug.WriteLine("BeginInvoke");
await Dispatcher.BeginInvoke((Action)(() => { rb.IsChecked = true; }));
Debug.WriteLine("EndInvoke");
}
private async void rb_Checked(object sender, RoutedEventArgs e)
{
await SomethingAfterChecked();
}
private async Task SomethingAfterChecked()
{
string abc = string.Empty;
await Task.Run(() => abc = "RbCheckedChanged");
Console.WriteLine(abc);
}
И MainWindow.xaml выглядит так:
<Window x:Class="AsyncAwaitIssue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AsyncAwaitIssue"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
Loaded="Window_Loaded"
mc:Ignorable="d">
<Grid>
<RadioButton x:Name="rb"
Checked="rb_Checked"
Content="CheckedOrNot"
IsChecked="False" />
</Grid>
</Window>
Ответ №1:
Это сама природа async void
методов. Когда вы установите IsChecked
, он будет ждать выполнения обработчика событий для измененного события, но когда вы выполняете этот обработчик, все, что вы когда-либо делаете, это запускаете асинхронную операцию. Обработчик завершится до завершения этих асинхронных операций.
В идеале вы должны избегать такой ситуации. Если у вас есть что-то, что должно произойти после работы, которую вы выполняете в событии changed, было бы лучше, если бы это событие change выполнило эту операцию. Если вы не можете, вам нужно будет вручную создать некоторую форму связи между этими разделами кода и связать эти операции вместе довольно плотно.
Комментарии:
1. Спасибо за ваш ответ Servy.
2. Я ожидал такого ответа, но я хотел посмотреть, есть ли решение для этого. Однако нам нужно будет найти другой способ обойти эту «проблему».