我尝试使用来自我的MessagingCenter的ViewModel来实现MVVM。我获得了以下错误,因为多个线程接收到相同的消息"ClearStackLayout“,并且不等待回调的结束:
索引超出了数组的界限。
以下是我的视图代码:
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);
}
});
}
}发布于 2016-05-29 10:11:55
首先,总是在UI线程上调用StackLayout.Children.Clear|Add。iOS不喜欢将UIView子视图从主UI线程中移除,并且会引发异常,甚至可能导致本机崩溃。
这就是我如何serialized消息传递调用的方式:
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.Release和catch,以执行添加/清除故障所需的任何恢复程序代码。
UIUnit并行测试方法:
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 AddToStackLayout和ClearStackLayout__的方法包装器。
https://stackoverflow.com/questions/37486027
复制相似问题