几周后,我终于重新使用新的6.0版本更新了我的MonoTouch iOS应用程序。对于长时间运行的活动(我的应用程序使服务调用后台并进行图像上传),我使用的线程非常类似于示例。这一切都很有效,直到我升级。控制器中的典型模式如下:
protected void LogInButtonClicked(object sender, EventArgs e)
{
NetworkActivity.Start();
// start the request.
ThreadPool.QueueUserWorkItem ((cb) => {
var service = new ClientUserService();
var result = service.Login(this.UserName.Text, this.Password.Text);
// when done, switch back to UI.
this.InvokeOnMainThread (() => {
NetworkActivity.Stop();
// do the various other things to init the app on the UI thread.
}
});
}
在5.x上工作得很好,从未崩溃过。它遵循公布的代码指南。但是现在我立即得到了UUIKit Consistency错误的例外:你正在调用一个只能从UI线程调用的UIKit方法。我在我的服务电话专线(service.Login(...))上得到了。
所以......我不确定我在这里做错了什么。我确实回过头来看一些较新的样本。其中一些人正在使用任务库(例如https://github.com/xamarin/mobile-samples/blob/master/MultiThreading/iOSMultiThreading/Screens/MainScreen_iPhone.cs),但这不应该排除这个QueueUserWorkItem方法。
问题:Monotouch中的线程模型是否有重大变化,因此不再支持上述编码模式?
感谢。 JB
答案 0 :(得分:6)
在InvokeOnMainThread委托中包装this.UserName.Text和this.Password.Text。 Monotouch希望所有使用UI元素的工作都在UI线程中执行。
答案 1 :(得分:3)
此功能不久前在MonoTouch 5.4中引入(请参阅新库功能,跨线程UI检查)。
现在这不是线程更改(代码像以前一样执行),而只是额外的检查以确保人们被警告有一个常见的陷阱 - 这通常很难调试。
如果您希望旧行为,请说明。但是请注意,您当前的代码已被破坏,虽然它可能在99%的时间内工作,但对于某些人来说可能会出现严重问题(例如,此类问题通常取决于时间,更改代码或使用不同的设备可能会触发问题)。
因此我强烈建议你解决这些问题,因为你发现它们(你的用户会喜欢你;-)就像Ben描述的那样。