【问题标题】:Xamarin UI gets updated in 10 seconds after OnPropertyChanged() triggeredXamarin UI 在 OnPropertyChanged() 触发后 10 秒内更新
【发布时间】:2017-12-21 03:24:10
【问题描述】:

一个非常奇怪的场景......也许有人可以提供帮助。让我头疼。

private string _myText = "Hello";
public string MyText
{
    get { return _myText; }

    set
    {
        _myText = value;
        OnPropertyChanged();
        //OnPropertyChanged("IsSearching");
    }
}

我将 MyText 绑定到 XAML Xamarin 视图中的标签,以调试运行此方法时发生的情况。

private async void Edit_Survey_Button_OnClicked(object sender, EventArgs e)
{
    MyText = "Text Before Long Method";
    Stopwatch s = new Stopwatch();
    await Task.Run(() =>
    {
        s.Start();
        Task.Delay(3000).Wait();
        MyText = "Text after long method" + s.ElapsedMilliseconds.ToString();
    });
}

因此,当单击按钮时,文本会更新,这太棒了,但它只会在 10-15 秒内更新第二次,而应该在 3 秒内更新!我不知道为什么,我已经尝试了很多关于如何运行它的选项,但我想这可能与将 MyText 设置在不同的线程上有关。

我正在做这个测试,因为我将下载数据而不是延迟,并且在数据下载之后,我想从初始状态更改一些 UI 元素。现在我对如何做到这一点非常怀疑,希望其他人也遇到过类似的情况。

________SushiHangover 建议的更新 1

    private void Edit_Survey_Button_OnClicked(object sender, EventArgs e)
    {
        IsSearching = "Method Start Edit";

        Task.Run(async () =>
        {
            await Task.Delay(3000);

            Device.BeginInvokeOnMainThread(() => { IsSearching = "Yeeeeehuuuuuuu!"; });


        });
    }

没有帮助;

【问题讨论】:

  • 您使用.Wait() 同步阻塞,请改用await Task.Delay(3000);。然后在您的TaskRun 中将MyText 分配包装在Device.BeginInvokeOnMainThread 中。
  • 不幸的是这不起作用
  • 不过,这完全有道理,我插入了关于如何实现您提到的内容的更新。不过还是不行。标签会在 20 秒内更新...
  • 你试过我的建议了吗?你在 UI 线程上做其他事情吗?
  • 是的,我刚才试过了。我所知道的 UI 线程上没有发生任何其他事情。

标签: c# user-interface xamarin


【解决方案1】:

试试这个:

private async void Edit_Survey_Button_OnClicked(object sender, EventArgs e)
{
    MyText = "Text Before Long Method";
    Stopwatch s = new Stopwatch();
    s.Start();
    await Task.Delay(3000);
    s.Stop();
    MyText = "Text after long method" + s.ElapsedMilliseconds.ToString();
}

【讨论】:

  • 不起作用,标签会更新,但仅在 20 秒内,我完全同意让延迟等待是完全有意义的,所以在工作完成后我们会回来更改 MyText 但它只是没有立即更新 UI,我不知道究竟是为什么。
  • 我建议你在一个新的空白应用程序中尝试这个,肯定没有其他事情发生......
  • 我试过了,同样的故事,但是如果我不是在 Xamarin 上下文中而是在一个简单的控制台应用程序的上下文中尝试它,它运行完美。值在控制台中更新。在 Xamarin 值在 20-25 秒内更新的情况下。
【解决方案2】:

我在 IOs 模拟器和 Android 中运行了这段代码,它运行良好:

namespace Yuri1
{
public partial class Yuri1Page : ContentPage
{
    async void Handle_Clicked(object sender, System.EventArgs e)
    {
        Stopwatch s = new Stopwatch();
        await Task.Run(() =>
        {
            s.Start();
            Task.Delay(3000).Wait();

        });

        MyEntry.Text="Text after long method: " + s.ElapsedMilliseconds.ToString();

    }


        //MyText.Text = "Text after long method" + s.ElapsedMilliseconds.ToString();        }

    public Yuri1Page()
        {
            InitializeComponent();
        }


}


}

【讨论】:

  • 我也同意上面的例子,在 BeginInvokeOnMainThread 中敲击它应该修复它
【解决方案3】:

非常感谢参与此讨论的每个人。因此,经过无数次尝试来弄清楚这一点,最合适的解决方案似乎是这样的。在延迟任务完成后更新 UI 所需的延迟似乎可以正常工作。在示例中,我调试了线程 ID,并尝试了两种类型的绑定 x 引用和数据绑定。

  List<string> threads = new List<string>();

    private BindableProperty IsSearchingProperty =
        BindableProperty.Create("IsSearching", typeof(string), typeof(MainPage), "Hello");

    public string IsSearching
    {
        get { return (string)GetValue(IsSearchingProperty); }
        set { SetValue(IsSearchingProperty, value); }
    }

    public MainPage()
    {
        BindingContext = this;
        InitializeComponent();
        threads.Add(GetThreadId() + " in constructor");
    }

    private string GetThreadId()
    {
        return Thread.CurrentThread.ManagedThreadId.ToString();
    }

    private async void Button_OnClicked(object sender, EventArgs e)
    {
        threads.Add(GetThreadId() + " in method");

        IsSearching = "Method Start Edit";
        MyRef.Text = "Reference Text Start";
        Stopwatch s = new Stopwatch();

        await Task.Run( () =>
        {
            threads.Add(GetThreadId() + " in task");
            s.Start();
            Task.Delay(3000).Wait();


            Device.BeginInvokeOnMainThread(() =>
            {
                IsSearching = "Yeeeeehuuuuuuu!";
                MyRef.Text = "Reference Text End" + s.ElapsedMilliseconds.ToString(); ;
                threads.Add(GetThreadId() + " in task in device begin invoke");
            });
        });

        threads.Add(GetThreadId() + " after task");
        DisplayAlert("My Threads", DiplayThreadInfo(), "Cancel");
        threads = null;

    }

    private string DiplayThreadInfo()
    {

        string threadsInfo = null;

        foreach (var thread in threads)
        {
            threadsInfo ="/"+ threadsInfo + thread + "/"+ Environment.NewLine;
        }

        return threadsInfo;
    }
}

线程调试后我们可以看到UI更新是在UI线程中执行的。这似乎是至关重要的,如果不这样做,问题就会开始发生。总的来说,这似乎可以完成这项工作。谢谢大家。

【讨论】:

  • 但有趣的是,如果您尝试更新 IsVisible,问题会再次出现。
猜你喜欢
  • 2021-02-13
  • 2019-05-26
  • 2016-08-30
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
相关资源
最近更新 更多