Czekanie na metodę przy zamykaniu okna

0

Witam. Mam problem z zapisem danych, po kliknięciu "X" w programie. Mój kod, w skrócie wygląda tak:

 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Save();
}
private async void Save()
{
//działania na wątku okna
//Tutaj funkcje  await Task.Run(() => metoda()));
}

Niestety, wątek okna nie czeka na wykonanie się kodu z "await"... Nie mam pojęcia czemu. Jak ustawie:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Close = true;
Save();
}

Wszystko działa jak należy. Poza tym, że oko się nie zamknie...

Wie ktoś może jak rozwiązać ten problem ?
Proszę o pomoc.
Pozdrawiam.

0
         protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            if (MessageBox.Show("Czy na pewno chcesz zakończyć ?",
              "Zamknac?", MessageBoxButton.YesNo, MessageBoxImage.Question)
                      == MessageBoxResult.No)
                e.Cancel = true;
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
//****************************
            //tu zapisujsz
        }
0

Sorki, pomyłka ;)

0

Zrobiłem tak jak radziłeś:

   protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            if ((Password_listView.Items.Count > 0) && (IsSave == false))
            {
                if (MessageBox.Show("Czy chcesz zapisać zmiany ?", "Zapis", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                {
                    e.Cancel = true;
                }
            }
        }
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            Save();
        }

Dostaję takie błędy:
Ważność Kod Opis Projekt Plik Wiersz
Błąd No overload for 'OnClosing' matches delegate 'CancelEventHandler',
oraz
Ważność Kod Opis Projekt Plik Wiersz
Błąd CS0123 Żadne z przeciążeń dla elementu „OnClosing” nie pasuje do delegata „CancelEventHandler”.

PS: Piszę w WPF, może ten kod jest dla WinForms ?

0

Tak zrób:

        public MainWindow() {
            InitializeComponent();

            var task = new Task(new Action(() => {
                var upperLimit = 1000000000;
                for (int i = 0; i < upperLimit; ++i) { }
            }));
            task.Start();

            this.Window.Closing += (sender, e) => {
                var result = MessageBox.Show("Czy chcesz zamknąć okno?", "", MessageBoxButton.YesNo, MessageBoxImage.Question);
                switch (result) {
                    case MessageBoxResult.Yes:
                        {
                            if (!task.IsCompleted) {
                                MessageBox.Show("Zadanie nie zostało zakończone.");
                                e.Cancel = true;
                            }
                            break;
                        }
                    case MessageBoxResult.No:
                        {
                            e.Cancel = true;
                            break;
                        }
                }
            };
        }

A jeśli chcesz wykonać jakieś zmiany w GUI użyj Dispatcher'a. Ustaw sobie duży upperLimit żebyś zdążył zobaczyć, że okno się nie zamknie dopóki trwa zadanie.

0

@grzesiek51114, czemu mam wywołać funkcję Save(), w konstruktorze ?
Ja potrzebuję ją wykonać dopiero przy zamykaniu okna.

private void Save()
{
//coś tam z oknem
await Task.Run(() => metoda()));
await Task.Run(() => metoda()));
//koniec
}
0

No przecież to co napisałem to jest tylko przykład, żebyś sobie po swojemu rozpisał. Zrób całego sejwa jako task'a i sprawdzaj przy zamknięciu czy zakończył działanie. Jak nie to po prostu nie zamykaj okna.

0

A dobra... wiem o co Ci chodzi. :D Nie zajarzyłem na początku. Żeby nie zapętlił Ci się event zamykania okna musisz sprawdzać status obiektu task.
Tak będzie dobrze:

        public MainWindow() {
            InitializeComponent();

            var task = new Task(new Action(() => {
                for (int i = 0; i < int.MaxValue; ++i) { }
            }));

            this.Window.Closing += (sender, e) => {
                if (task.Status != TaskStatus.Running && task.IsCompleted != true) task.Start();
                var result = MessageBox.Show("Czy chcesz zamknąć okno?", "", MessageBoxButton.YesNo, MessageBoxImage.Question);
                switch (result) {
                    case MessageBoxResult.Yes:
                        {
                            if (!task.IsCompleted) {
                                MessageBox.Show("Zadanie nie zostało zakończone.");
                                e.Cancel = true;
                            }
                            break;
                        }
                    case MessageBoxResult.No:
                        {
                            e.Cancel = true;
                            break;
                        }
                }
            };
        }
0

Nie działa :/

Sam sprawdź, uruchom tym taką metodę:

  private void Save()
        {
            MessageBox.Show("a");
        }

Zapętla się...

1

Przecież działa i nic się nie zapętla, bo nie może!

        public MainWindow() {
            InitializeComponent();

            var task = new Task(this.Save);

            this.Window.Closing += (sender, e) => {

                // TO jest kluczowa linijka:
                if (task.Status != TaskStatus.Running && task.IsCompleted != true) task.Start();

                var result = MessageBox.Show("Czy chcesz zamknąć okno?", "", MessageBoxButton.YesNo, MessageBoxImage.Question);
                switch (result) {
                    case MessageBoxResult.Yes:
                        {
                            if (!task.IsCompleted) {
                                MessageBox.Show("Zadanie nie zostało zakończone.");
                                e.Cancel = true;
                            }
                            break;
                        }
                    case MessageBoxResult.No:
                        {
                            e.Cancel = true;
                            break;
                        }
                }
            };
        }

        private void Save() {
            MessageBox.Show("a");
        }

EDIT: Póki nie zamkniesz messagebox'a z literą program nie pozwoli Ci zamknąć okna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0