【问题标题】:Button click event with a task not updating ui带有未更新 ui 的任务的按钮单击事件
【发布时间】:2020-02-23 22:54:03
【问题描述】:

我有一个按钮单击事件,它在其中执行一项很长的任务(可能从 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();


            }
        }

每当触发事件时,用户界面都不会更新,直到任务完成。即使我在事件触发后立即调用的 UI 更新也不会在任务完成之前发生。我该怎么办?

更新:这对我有用

        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));
                }
            });
        }

【问题讨论】:

    标签: c# xamarin.forms task


    【解决方案1】:

    您可以尝试在不同的线程中运行您的代码,并在线程方法中使用委托(操作)更新 UI - 添加\删除对(来自)线程方法的其他调用。 例如:

    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();
        }
    

    【讨论】:

      【解决方案2】:
      Device.BeginInvokeOnMainThread (() => {
       //put your UI updates here
      });
      

      这将强制您的代码在主线程上执行它。 同样删除.Wait();,就像彼得说的那样,会导致死锁。

      【讨论】:

      • 谢谢,这与 San 回答中的任务相结合对我有用。我会用有效的代码更新它
      猜你喜欢
      • 1970-01-01
      • 2016-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-02-26
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      相关资源
      最近更新 更多