首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >以Xamarin形式等待MessagingCenter

以Xamarin形式等待MessagingCenter
EN

Stack Overflow用户
提问于 2016-05-27 14:28:05
回答 1查看 5.7K关注 0票数 1

我尝试使用来自我的MessagingCenter的ViewModel来实现MVVM。我获得了以下错误,因为多个线程接收到相同的消息"ClearStackLayout“,并且不等待回调的结束:

索引超出了数组的界限。

以下是我的视图代码:

代码语言:javascript
复制
public partial class LibraryChoicePage : DefaultBackgroundPage {

        private Object thisLock = new Object();

        public LibraryChoicePage() {
            InitializeComponent();

            /* ClearStackLayout */
            MessagingCenter.Subscribe<LibraryChoiceViewModel>(this, "ClearStackLayout", (sender) => {
                lock (thisLock) {
                    this._choices.Children.Clear();
                }
            });

            /* AddToStackLayout */
            MessagingCenter.Subscribe<LibraryChoiceViewModel, View>(this, "AddToStackLayout", (sender, arg) => {
                lock (thisLock) {
                    this._choices.Children.Add(arg);
                }
            });

        }

    }
EN

回答 1

Stack Overflow用户

发布于 2016-05-29 10:11:55

首先,总是在UI线程上调用StackLayout.Children.Clear|Add。iOS不喜欢将UIView子视图从主UI线程中移除,并且会引发异常,甚至可能导致本机崩溃。

这就是我如何serialized消息传递调用的方式:

代码语言:javascript
复制
var semaphone = new SemaphoreSlim(1);
MessagingCenter.Subscribe<object>(this, "ClearStackLayout",  async (sender) =>
{
    await semaphone.WaitAsync();
    Device.BeginInvokeOnMainThread(() =>
    {
        _choices.Children.Clear();
    });
    semaphone.Release();
});

MessagingCenter.Subscribe<object, View>(this, "AddToStackLayout", async (sender, arg) =>
{
    await semaphone.WaitAsync();
    Device.BeginInvokeOnMainThread(() =>
    {
        _choices.Children.Add(arg);
    });
    semaphone.Release();
});

注意:try/finally应该包装SemaphoreSlim.Releasecatch,以执行添加/清除故障所需的任何恢复程序代码。

UIUnit并行测试方法:

代码语言:javascript
复制
Random random = new Random();
var tasks = new List<Task>();
for (int i = 0; i < 50; i++)
{
    if (random.NextDouble() > .1)
        tasks.Add(Task.Factory.StartNew(() => { AddLayout(); }));
    else
        tasks.Add(Task.Factory.StartNew(() => { ClearLayout(); }));
}
var completed = Task.Factory.ContinueWhenAll(tasks.ToArray(), (messagecenterTasks) => { 
    foreach (var task in messagecenterTasks)
    {
        if (task.Status == TaskStatus.Faulted)
        {
            D.WriteLine("Faulted:");
            D.WriteLine($"  {task.Exception.Message}");
        }
    }
}).Wait(1000);
if (!completed)
    D.WriteLine("Some tasks did not complete in time allocated");

注意: AddLayout/ClearLayout是MessageCenter.Send of AddToStackLayoutClearStackLayout__的方法包装器。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37486027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档