访问 UI 组件并由 Xamarin 中的另一个线程覆盖它

Posted

技术标签:

【中文标题】访问 UI 组件并由 Xamarin 中的另一个线程覆盖它【英文标题】:Accessing UI component and overwrite it by another thread in Xamarin 【发布时间】:2020-07-07 10:38:04 【问题描述】:

所以我已经尝试解决这个问题几个小时了,我几乎放弃了。 必须有一种方法可以在另一个线程后面访问 Xamarin C# 代码上的普通标签。

这就是我基本上在做的事情:

namespace Traktor

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class TrackerPage : ContentPage
    
        public delegate void TrackedTimeUpdateHandler(double elapsedTime);    // Delegate to notify the TrackingPage of how much time elapsed
        private TimeTracker tracker;

        // Ctor, and other methods etc. are here
        // ...

        // Initialize the tracker and add handler to it (called in Ctor)
        void Initialize()
        
            tracker = new TimeTracker();
            tracker.TrackedTimeUpdate += new TrackedTimeUpdateHandler(UpdateGUI);
        

        // This method is called periodically by the inner thread of 'tracker'
        void UpdateGUI(double elapsedTime)
        
            // Status label is a label on the page this refers to
            statusLabel.Text = String.Format("0:F2", elapsedTime); 
            // Throws exception: "android.Util.AndroidRuntimeException: 'Only the original thread that created a view hierarchy can touch its views.'"
        
    

一个单独的线程在TimeTracker tracker 中运行,它不断引发一个事件来通知这个 TrackerPage 已经过去了多少时间。然后调用UpdateGUI(...)- 方法。那只是将 statusLabel 的文本设置为经过的时间。一切都像魅力一样。但我无法通过 UI-Thread 本身以外的另一个线程访问statusLabel.Text

我已经尝试了这么多,这很烦人,因为大多数情况下都丢失了一些东西,或者其他东西不起作用。比如statusLabel不是实现ISynchronizeInvoke的Class,或者我不能使用System.Windows.Forms.Control-命名空间。我不知道为什么。

所以我的问题是: 有没有办法访问标签(我的ContentPage 上的 UI 的一部分)并从另一个线程修改它(或以任何方式使elapsedTime 可以定期显示)?我不能调用和异步似乎不适合这里。我真的不知道如何解决这个问题。或者是否有在 UI 线程上调用的 Xamarin 原生方式?


到目前为止我所尝试的:

1 Best Way to Invoke Any Cross-Threaded Code?

2https://***.com/a/711419/9984792

3 https://***.com/a/7610035/9984792

4https://***.com/a/7610016/9984792

-> 我不能使用System.Windows.Forms.Control- 命名空间。我不知道为什么。也许是因为 Xamarin 不希望我这样做。所以我无法访问System.Windows.Forms.Control.Invoke 等。

【问题讨论】:

docs.microsoft.com/en-us/xamarin/essentials/main-thread 非常感谢!老实说,我不知道为什么我没有偶然发现。你能回答吗?或者我应该回答这个问题,以便我可以宣布这个问题已结束? 【参考方案1】:

Essentials 包含一个帮助类来强制您的代码在主 UI 线程上执行

MainThread.BeginInvokeOnMainThread(() =>

    // Code to run on the main thread
);

【讨论】:

有趣的是,我试过这个,但没有用。我尝试的第二次确实有效。我不知道,但它很奇怪。无论如何,非常感谢你!这对我很有帮助!

以上是关于访问 UI 组件并由 Xamarin 中的另一个线程覆盖它的主要内容,如果未能解决你的问题,请参考以下文章

通过从 flex 中的另一个 mxml 文件访问组件来使组件不可见

我们如何使分隔线高度等于 SWIFT UI 小部件中水平堆栈的另一个子级

Xamarin 绑定到列表视图项模板中的另一个元素

实现多列下拉框组件的另一种思路(element-ui 多列下拉框)

如何从 Xamarin MacOS 开发中的另一个 C# 文件更新 ViewController.cs 中的“标签”?

ScrollView 在 Xamarin Forms 中的另一个 ScrollView 内