WPF:窗口上的异步操作关闭

问题描述 投票:0回答:1
我需要在关闭窗口时执行异步操作(基本上是为了保存所有数据)。问题在于程序和UI线程死亡太早了,任务永远不会完成。

这是代码示例:

public partial class MainWindow : Window { public MainWindow() { Closed += MainWindow_Closed; _items = new(Enumerable.Range(0,10)); } private ObservableCollection<int> _items; private async void MainWindow_Closed(object? sender, EventArgs e) { await LongTask(); } private async Task LongTask() { await Task.Run(() => { Trace.WriteLine("LongTask Start"); Application.Current.Dispatcher.BeginInvoke(() => { // do some action in the UI thread _items.Clear(); Trace.WriteLine("Cleared elements"); }); Thread.Sleep(5000); Trace.WriteLine("LongTask End"); }); } }

控制台输出切勿打印“已清除元素”或“ longtask end”。
我还在异步任务中提出了一个操作,它需要UI线程来完成操作,这在我的用例中需要。 (因此,一个人不能在主线程中使用longtask()。getawaiter()。getResult(),因为它会导致死锁)。
thanks寻求帮助!!

作为概念证明,这是您可以做到这一点的一种方法。这里的关键是

_confirmClosure
c# wpf asynchronous task
1个回答
0
投票

UI可以防止任何重新进入的机会

同时执行保存。
,然后在等待保存之后,再次致电

Close
    ,这次是
  • _confirmClosure
  • 设置为`false。
  • public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Loaded += (sender, e) => { if(dataGrid.Columns .OfType<DataGridTextColumn>() .FirstOrDefault(c => c.Header.ToString() == "Name") is { } column) { // Autosize "Fill" for item name column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); } }; Closing += async (sender, e) => { if (_confirmClosure) { switch ( MessageBox.Show( "Do you want to save before closing?", "Confirm Exit", MessageBoxButton.YesNoCancel, MessageBoxImage.Question)) { case MessageBoxResult.Yes: e.Cancel = true; await Dispatcher.BeginInvoke(async () => { IsEnabled = false; // Prevent any more calls. await DataContext.Save(); _confirmClosure = false; Close(); }); break; case MessageBoxResult.No: break; case MessageBoxResult.Cancel: e.Cancel = true; break; } } }; } bool _confirmClosure = true; new MainPageViewModel DataContext => (MainPageViewModel)base.DataContext; }
  • test测试的少量VM
    
    我们将列出10000个项目的“大”列表,然后在关闭时将其保存到文件中。
    public class MainPageViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Item> Items { get; } = new ObservableCollection<Item>(
                Enumerable.Range(1, 10000)
                .Select(_=>new Item { Id = _, Name = $"Item {_}" }));
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        internal async Task Save()
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                await Task.Run(() =>
                {
                    var path = Path.Combine(
                        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                        "StackOverflow",
                        Assembly.GetEntryAssembly()?.GetName()?.Name ?? "SaveThenClose");
                        var json = JsonConvert.SerializeObject(Items);
                    File.WriteAllText(path, json);
                });
                // Add a few seconds for good measure, just for demo purposes.
                await Task.Delay(TimeSpan.FromSeconds(2.5));
            }
            finally
            {
                // Reset the cursor to default
                Mouse.OverrideCursor = null;
            }
        }
    }
    
    public class Item
    {
        public int Id { get; set; }
        public string? Name { get; set; }
    }
    
  • <Window x:Class="save_list_then_close.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:save_list_then_close" mc:Ignorable="d" Title="MainWindow" Height="250" Width="400" WindowStartupLocation="CenterScreen"> <Window.DataContext> <local:MainPageViewModel/> </Window.DataContext> <Grid> <DataGrid Name="dataGrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True" IsReadOnly="True" AlternatingRowBackground="LightGray"/> </Grid> </Window>
	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.