Событие нажатия кнопки с задачей, не обновляющей пользовательский интерфейс - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть событие нажатия кнопки, которое выполняет длинную задачу внутри него (может варьироваться от 3 с до 3 минут)

        private void B_Clicked(object sender, EventArgs e)
        {
            bumpPop.Dismiss();
            SfPopupLayout loadPop = new SfPopupLayout();
            DataTemplate loadView = new DataTemplate(() =>
            {
                SfBusyIndicator busy = new SfBusyIndicator();
                return busy;
            });
            loadPop.PopupView.ContentTemplate = loadView;
            loadPop.Show();
            if (String.IsNullOrEmpty((string)gradeSel.SelectedValue) || String.IsNullOrWhiteSpace((string)gradeSel.SelectedValue))
            {
                gradeSel.Watermark = "Please select a grade";
                loadPop.Dismiss();
                bumpPop.Show();
            }
            else
            {
                string grade = (string) gradeSel.SelectedValue;

                Task.Run(() => BumpGrade(grade)).Wait();
                UpdateOverallScore();
                AssList.ItemsSource = Asses;
                loadPop.Dismiss();


            }
        }

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

ОБНОВЛЕНИЕ: Это то, что у меня сработало

        private async void B_Clicked(object sender, EventArgs e)
        {
            await PreBumpWork();
            Device.BeginInvokeOnMainThread(() => {
                loadPop.Dismiss();
                loadPop.IsOpen = false;
                loadPop.IsVisible = false;
            });
        }

        private Task PreBumpWork()
        {
            return Task.Factory.StartNew(() =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    bumpPop.Dismiss();
                    DataTemplate loadView = new DataTemplate(() =>
                    {
                        SfBusyIndicator busy = new SfBusyIndicator();
                        busy.IsBusy = true;
                        return busy;
                    });
                    loadPop.PopupView.ContentTemplate = loadView;
                    loadPop.PopupView.ShowFooter = false;
                    loadPop.PopupView.ShowHeader = false;
                    loadPop.ClosePopupOnBackButtonPressed = false;
                    loadPop.Show();
                });

                if (String.IsNullOrEmpty((string)gradeSel.SelectedValue) || String.IsNullOrWhiteSpace((string)gradeSel.SelectedValue))
                {
                    Device.BeginInvokeOnMainThread(() => {
                        gradeSel.Watermark = "Please select a grade";
                        loadPop.Dismiss();
                        bumpPop.Show();
                    });
                }
                else
                {
                    string grade = (string)gradeSel.SelectedValue;

                    Task.Run(async () => await BumpGrade(grade));
                }
            });
        }

Ответы [ 2 ]

1 голос
/ 23 февраля 2020

Вы можете попробовать запустить свой код в другом потоке, а в методе потока обновить пользовательский интерфейс с помощью делегата (Action) - добавить \ удалить другие вызовы (из) метода потока. Например:

private void B_Clicked(object sender, EventArgs e)
    {
        bumpPop.Dismiss();
        SfPopupLayout loadPop = new SfPopupLayout();
        DataTemplate loadView = new DataTemplate(() =>
        {
            SfBusyIndicator busy = new SfBusyIndicator();
            return busy;
        });
        loadPop.PopupView.ContentTemplate = loadView;
        loadPop.Show();
        if (String.IsNullOrEmpty((string)gradeSel.SelectedValue) || String.IsNullOrWhiteSpace((string)gradeSel.SelectedValue))
        {
            gradeSel.Watermark = "Please select a grade";
            loadPop.Dismiss();
            bumpPop.Show();
        }
        else
        {
            string grade = (string)gradeSel.SelectedValue;
            object val = new string[] { grade, loadPop };
            Thread thread = new Thread(MyMethod);
            thread.Start(val);
        }
    }

    private void MyMethod(object Data)
    {
        Invoke(new Action(() => UpdateApplicationUI(Data)));
    }

    private void UpdateApplicationUI(object Data)
    {
        object[] items = (object[])Data;
        string grade = items[0] as string;
        SfPopupLayout loadPop = items[1] as SfPopupLayout;
        BumpGrade(grade);
        UpdateOverallScore();
        AssList.ItemsSource = Asses;
        loadPop.Dismiss();
    }
0 голосов
/ 23 февраля 2020
Device.BeginInvokeOnMainThread (() => {
 //put your UI updates here
});

Это заставит ваш код выполнять его в основном потоке. Также удалите .Wait();, как сказал Питер, это приведет к тупику.

...