天道酬勤,学无止境

Detecting when you're in/out of the main thread in Xamarin.iOS

Is there a way in Xamarin/MonoTouch to detect whether code is being called in the main thread?

I'm looking for something like the equivalent of Java's EventQueue.isEventDispatchThread() -- I've found in Swing programming it's handy to assert that from time to time (or sometimes to assert that it's not) -- making sure that models are consistently updated and read from the EDT, and that long-running calls don't block the UI.

I'd like to do the same in my MonoTouch app, to ensure that various bits of code are/aren't called from the UI, or wrapped in InvokeOnMainThread.


Updated: For anyone coming along later: Obj-C answer from JP below . The Xamarin/MonoTouch equivalent is NSThread.Current.IsMainThread.

评论

I don't know much about Monotouch, but in iOS +[NSThread isMainThread] might be what you're looking for.

Occasionally when writing multithreaded code, I will put in an assert like this:

NSAssert([NSThread isMainThread], @"Method called using a thread other than main!");

The only problem with NSAssert([NSThread isMainThread], errorDesc) is that you BETTER be in the main thread when making this call. If you happen to be in a secondary thread and make the call then your application crashes! So it's kind of pointless.

It's better just to simply use [NSThread isMainThread] then assess the BOOL value it returns.

You can do like this in Monotouch / Xamarin.ios

        if (NSThread.Current.IsMainThread)
        {
            //You are in the MainThread
        } 

This check is very useful to avoid the error that might occur when trying to modify the UI from a background Thread. Something Like this can be done:

if (NSThread.Current.IsMainThread)
{
    DoSomething();
}
else
{
    BeginInvokeOnMainThread(() => DoSomething());
}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 在 iOS8 的 UITextField 中检测退格(Detect backspace in UITextField in iOS8)
    问题 为了检测 Backspace,我重写了DeleteBackward方法(应该适用于 iOS5+) var input = new BackspaceTextField(RectangleF.Empty); etc input.BecomeFirstResponder(); 这是代码 public sealed class BackspaceTextField : UITextField { public BackspaceTextField(RectangleF frame) : base(frame) { } public override void DeleteBackward () { Console.WriteLine ("DeleteBackward"); } } 当我按下“Backspace”按钮时,什么也没有发生。 我希望应该出现“DeleteBackward”消息 环境:iOS8、xamarin 编辑:0 Objective-c 上的类似问题:Detect backspace in UITextField 我已经做了额外的检查。 DeleteBackward是 UIKeyInput 协议中的方法,所以我检查了insertText方法,这个方法非常有效。 public override void InsertText (string text) { base
  • How to start GPS tracking triggered by a iBeacon in Xamarin iOS?
    I am working on an app that records journeys by tracking the GPS. Everything is working fine in background if we start the process from the foreground (by tapping the button "Start Journey"). Now the idea is start record these journeys automatically triggered by a iBeacon. When the iPhone gets inside of a beacon region, the app is detecting this and calls the function LocationManager.StartUpdatingLocation(); PROBLEM: Using iBeacons from background, we only get 10 seconds ranging and that is the same figure I have got to get location updates from GPS. All I need is detect I am inside of beacon
  • 无法在 iOS 上的 Azure NotificationHub 中注册设备,没有回调(Cannot register device in Azure NotificationHub on iOS, no callbacks)
    问题 我正在尝试通过 Azure NotificationHub 设置推送通知(使用这些指南)。 Android 运行良好,但 iOS... 无论我做什么,我都不会收到来自SBNotificationHub 的RegisterNative / RegisterTemplate方法的任何回调,并且集线器中也没有注册。 我的代码(非常简单): public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false) { try { var Hub = new SBNotificationHub(AppConstants.ListenConnectionString, AppConstants.NotificationHubName); Logger.WriteLine($"Unsubscribing from AzureHub [{deviceToken}]...."); Hub.UnregisterAll(deviceToken, (error) => { if (error != null) { Logger.WriteLine($"SubscribeToAzure: Unable to call unregister,
  • Error: ConnectFailure (Connection refused)
    I have the xamarin.forms application for which i am trying to connect localhost from PC to Iphone simulator in mac,Iam using the Ip address for connecting, private string Uri = "http://192.168.0.16:62271/";//Windows Ip address:localhost port number private string GetDishesUrl = "api/DishDetails/GetDishDetails?id=5"; try{ var httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(Uri); var response = await httpClient.GetAsync(new Uri(Uri + GetDishesUrl)); var stringAsync = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { var responseJson = stringAsync
  • 如何在 Xamarin iOS 中启动由 iBeacon 触发的 GPS 跟踪?(How to start GPS tracking triggered by a iBeacon in Xamarin iOS?)
    问题 我正在开发一个通过跟踪 GPS 来记录旅程的应用程序。 如果我们从前台开始进程(通过点击“开始旅程”按钮),那么在后台一切正常。 现在的想法是开始记录由 iBeacon 自动触发的这些旅程。 当 iPhone 进入信标区域时,应用程序会检测到这一点并调用函数LocationManager.StartUpdatingLocation(); 问题:在后台使用 iBeacons,我们只能获得 10 秒的测距,这与我从 GPS 获取位置更新所获得的数字相同。 我所需要的只是检测我在信标区域内,启动 GPS 并保持运行,只有当我在该区域外时才禁用 GPS。 回答1 我们实际上最近也想在我们的一个应用程序中实现这种行为,并且发现如果我们在前台启动重要的位置更新 (startMonitoringSignificantLocationChanges),那么我们就可以在后台启动常规位置更新 ( startUpdatingLocation ),在我们的didEnterRegion实现。 (当然,您的应用需要“始终”授权才能访问定位服务,并启用“位置更新”后台模式。) 我们的应用程序仍在等待审核,因此这是否是 Core Location 的错误或功能,以及 Apple 是否同意这一点还有待观察。 回答2 不幸的是,您可以在后台使用CoreLocation地理围栏,但无法持续获得精细的 GPS 更新
  • UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread
    I'm trying to run this code: GetRepsButton.Command = new Command(async () => { var url = @"https://url"; HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //crashes here var test = await client.GetStringAsync(url); }); And when I do, the entire app crashes and the output window shows this error: ROR: +[MSWrapperLogger MSWrapperLog:tag:level:]/7 Unhandled Exception: UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread. at UIKit
  • Xamarin 中使用 TLS 1.2 的 Https(Https with TLS 1.2 in Xamarin)
    问题 我在 Xamarin 中使用 HttpClient 向带有 TLS 1.2 的 https 请求,但出现如下错误; System.AggregateException: One or more errors occurred ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed. at Mono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc) [0x00013] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.9.1.3/src/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:574 at
  • OpenUrl将应用冻结10秒钟以上(OpenUrl freezes app for over 10 seconds)
    问题 我目前正在开发一个应用程序,该应用程序需要打开浏览器才能显示网页。 为此,我将[UIApplication sharedApplication] openURL方法与URL结合使用。 在iOS 6中,此功能运行良好,但在iOS 7中,该应用冻结了10秒钟以上,然后打开浏览器,一切都很好。 这是使用临时设置进行的。 互联网上有人评论说这是一个已知问题,但是关于这个问题我只能找到一条评论。 回答1 从iOS 7开始,从应用程序代表didReceiveRemoteNotification:或didFinishLaunchingWithOptions:调用-[UIApplication openUrl:]时,我注意到了相同的问题。 我通过使用GCD延迟了通话来解决了这个问题: // objc dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] openURL:url]; }); 它让iOS有一些时间来完成应用程序初始化,然后可以毫无问题地执行调用。 不要问我为什么。 这对您有用吗? 正如经常看到的这个答案,我添加了快速版本: // swift dispatch_async(dispatch_get_main_queue()) { UIApplication
  • iOS 屏幕截图作为 System.Drawing.Bitmap (Xamarin) 来自后台应用程序(iOS Screenshot as System.Drawing.Bitmap (Xamarin) from Background App)
    问题 对于越狱的 iOS 设备上的私人应用程序(=不会在任何应用程序商店上发布),我需要将整个屏幕的屏幕截图发送到后台。 已发布类似问题 iOS:是否可以在作为后台任务运行时截取屏幕截图? 得出的结论是,由于 iOS 的安全沙箱,在非越狱设备上这是不可能的如何从后台应用程序中截取运行 iPhone 的屏幕截图? 尚未确定,但似乎也针对非越狱设备如何在越狱的 iOS 设备上截取整个屏幕的截图? (和一些类似的越狱 iOS 从后台应用程序中截取屏幕截图)似乎接近我正在寻找的内容,但代码是用 Objective C 编写的,并使用了一个神秘的私有函数_UICreateScreenUIImage()我不知道在它定义了哪个模块(所以我不知道如何将其声明为外部函数)。 屏幕截图也作为 UIImage 返回(请参阅 http://developer.xamarin.com/api/type/MonoTouch.UIKit.UIImage/ ),我还不知道如何转换为 System.Drawing.Bitmap(请参阅https://developer.xamarin.com/api/type/System.Drawing.Bitmap/)。 以下是我的代码的帖子。 我正在寻求有关实现private System.Drawing.Bitmap ShootScreen() using System
  • 仅当应用程序打开并运行时如何在后台运行方法?(How to run a method in the background only when app is open and running?)
    问题 一旦应用程序打开并运行,我想要一个后台进程来检查数据库并根据数据库中的数据进行更新。 我想每分钟检查一次。 我只希望在应用程序处于前台并在用户看来时发生这种情况。 有人可以就我如何做到这一点给我一些建议吗? 我假设我可以从这里调用一个方法,但我不确定如何做到这一点。 此外,我不知道如何停止,甚至我是否需要手动取消/停止该过程。 当应用程序不在前台时它会自动取消并在应用程序回到前台时重新启动吗? public partial class App : Application { protected override void OnStart() { App.DB.InitData(); MainPage = new Japanese.MainPage(); } 但是我是否需要在不同的线程上运行它,如果是这样,我该怎么做。 对不起,如果我的问题不清楚。 请询问,如果没有意义,我可以更新。 回答1 我们在表单应用程序中所做的是利用 System.Diagnostics 和 Xamarin.Forms 中可用的 Device.Timer 和 Stopwatch 类来创建一个非常通用的托管计时器,我们可以使用 onStart、onSleep 和 onResume 与之交互Xamarin.Forms 中的方法。 这个特定的解决方案不需要任何特殊的平台特定逻辑,并且设备计时器和秒表是非 UI
  • 无法复制 Apple iOS 应用审查崩溃(Cannot replicate Apple iOS app review crash)
    问题 我最近将我的 iOS 应用程序提交给 Apple 进行审核。 它是用 C# 编写的,使用 Xamarin iOS、Monotouch 和 Monogame。 我使用 Xamarin IDE 进行开发。 一周后,我收到拒绝,其中说明原因是当审阅者尝试访问 In-App-Purchase 商店时应用程序在 iPad 上崩溃,而在 iPhone 5s 上它没有崩溃,但表明它不能到达 Apple 服务器以检索商店商品。 我的大部分商店检索代码都来自此处找到的 Xamarin 指南。 问题是我无法复制这些崩溃。 这家商店对我来说开得很好,我对它进行了广泛的测试。 我在所有模拟器和许多真实设备上进行了调试和发布配置(iPhone 4、iPhone 5、iPhone 5s、iPad 第 3 代)的测试。 我没有在 ad-hoc 模式下进行测试,因为其中许多设备都是从我的朋友那里借来的,而且我不想在 iTunes 中同步,因为这可能会清除设备数据。 因此,我希望发布版本和临时版本在查找审核团队的错误方面是等效的。 至于 Apple 给我的崩溃日志,它们对我没有帮助,因为使用我提交给 Apple 的相同存档在 Xcode 中大多数行都没有正确符号化。 日志中有很多 '___lldb_unnamed_function' 行。 我只能说是在尝试检索商店时发生了崩溃。 因此我被卡住了
  • 获取音频输入设备采样率时出错:'!obj'(Error getting audio input device sample rate: '!obj')
    问题 目前我正在开发一个应用程序,可以从互联网上播放广播电台。 我看了这个教程并一步一步地实现了它。 它工作了一段时间很好,但现在我收到以下错误,应用程序不会流式传输任何内容 2013-07-20 10:22:40.653 ShqipCom[464:c07] [MPAVController] Autoplay: Enabling autoplay 2013-07-20 10:22:40.668 ShqipCom[464:c07] [MPCloudAssetDownloadController] Prioritization requested for media item ID: 0 2013-07-20 10:22:41.129 ShqipCom[464:c07] [MPAVController] Autoplay: Enabling autoplay 2013-07-20 10:22:41.572 ShqipCom[464:7103] <com.apple.coremedia.networkbuffering> Error '!obj' trying to fetch default input device's sample rate 2013-07-20 10:22:41.574 ShqipCom[464:7103] <com.apple.coremedia
  • 检测TableView底部的伪代码(Pseudocode for detecting bottom of TableView)
    问题 我试图检测用户何时到达Xamarin.iOS中的表格底部。 我创建了这个伪代码是为了检测底部,但是一旦应用程序运行它就会打印它已经在表格的底部,而实际上它不是...... float height = tableView.Frame.Size.Height; float contentYoffset = tableView.ContentOffset.Y; float distanceFromBottom = tableView.ContentSize.Height - contentYoffset; if (distanceFromBottom < height) { Console.WriteLine ("Bottom of Table"); } 任何改进此代码的建议或任何更好的检测底部的方法? 这是我的 TableView.cs 类: public class TableView : UITableView, ITableCellProvider<Datum> { public TableView () { } public TableView (IntPtr handle) : base(handle) { } public UITableViewCell GetCell (Datum item) { var newCell = this
  • Pseudocode for detecting bottom of TableView
    I am trying to detect when the user gets to the bottom of the table in Xamarin.iOS. I have created this pseudocode in order to detect the bottom, however as soon as the application runs it prints that it is already at the bottom of the table when in fact it is not.. float height = tableView.Frame.Size.Height; float contentYoffset = tableView.ContentOffset.Y; float distanceFromBottom = tableView.ContentSize.Height - contentYoffset; if (distanceFromBottom < height) { Console.WriteLine ("Bottom of Table"); } Any suggestions to improve this code or any better methods of detecting the bottom? Here
  • Https with TLS 1.2 in Xamarin
    I'm using HttpClient in Xamarin to request to https with TLS 1.2 and I got the error as below; System.AggregateException: One or more errors occurred ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed. at Mono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc) [0x00013] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.9.1.3/src/mono/mcs/class/Mono.Security/Mono.Security
  • 从Xamarin.Essentials谈Xamarin库的封装
    编者语:Xamarin在国内的推广还需要努力,其实这真的是移动端开发的一大福音,毕竟用一份代码的时间可以生成iOS/Android/Windows/Linux/macOS/Tizen多个平台,而且是原生的性能。Xamarin在Build 2018发布的新功能有Xamarin.Essentials(点击查看) , Hyper-V for Xamarin Android Emulator ,还有Xamarin.Forms 3.0。Xamarin.Forms 3.0 和 Xamarin.Essentials 都会是一个质的飞跃。Xamarin.Forms 有全新的布局FlexLayout ,更好地和原生控件对接,还新增支持GTK+/Tizen。而Xamarin.Essentials的发布则大大提升开发的效率,把因为平台差异造成的代码不一致的底层接口重新做了归一,这样做提升了编码效率。 在Build2018前的两周左右,我拿到了Xamarin.Essentials的测试版本(基于nda我只能等到现在才能发布),这是一个为访问一些设备硬件和底层给iOS/Android/UWP三个平台做的统一接口,适配了.NET Standard 2.0(当然也包含.NET Standard 1.0 / iOS / Android)。通过Xamarin.Essentails你可以非常快捷地访问不同平台的摄像头
  • 使用.NET的Xamarin iOS本地化(Xamarin iOS localization using .NET)
    问题 我正在尝试在Xamarin iOS / Android项目的可移植类库中使用.NET本地化。 我已按照以下步骤操作: 如何在C#中使用本地化 并具有如下所示的代码: string sText = strings.enter_movie_name; Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr"); sText = strings.enter_movie_name; lblEnterMovieName.Text = sText; 我也尝试过: ResourceManager resman = new ResourceManager(typeof(MyApplication.strings)); string sText = resman.GetString("enter_movie_name", new CultureInfo("fr")); 我创建了strings.resx,其中enter_movie_name等于“输入电影名称:”,而strings.fr.resx等于“ Entre la电影名称:” 但是,sText总是以“输入电影名称:”结尾。 我似乎无法获得“ Entre la movie name:”的版本。 我还在跨平台本地化中看到了该帖子,但无法解决。
  • iOS Screenshot as System.Drawing.Bitmap (Xamarin) from Background App
    For a private app (=not to be published on any appstore) on a jailbroken iOS-Device I need to take screenshots of the entire screen from being sent to the background. Similar questions have been posted iOS: Is it possible to take screenshots while running as a background task? which concluded that it would be impossible on non-jailbroken devices due to iOS's security sandbox How to take screenshots of running iPhone from background app? is yet pending, but also seems to target non-jailbroken devices How to take screenshot of entire screen on a Jailbroken iOS Device? (and somewhat similar
  • 如何在 xamarin ios C# 中以编程方式触发 UIButton 的 TouchUpInside(How to fire TouchUpInside of UIButton Programmatically in xamarin ios C#)
    问题 我正在尝试以编程方式触发 Uibutton 的 touchupinside 事件。 我怎样才能做到这一点 ? 我尝试的代码使用 PerformSelector 但我收到此错误 "Error MT4117: The registrar found a signature mismatch in the method 'VCPAckage2.ActivityViewController.TouchUpInsideEvent' - the selector 'TouchUpInsideEvent:' indicates the method takes 1 parameters, while the managed method has 2 parameters. " 我想实现类似的东西 UIButton.FireEvent("TouchUpInsideEvent") - this will fire the TouchUpInsideEvent UIButton.PerformSelector(new MonoTouch.ObjCRuntime.Selector ("TouchUpInsideEvent:"), null, 2000f); 这是代码 private void LoadFn() { UIButton btnSubmit = new UIButton(new
  • How to add Xamarin Forms content as a subview in Xamarin.Android and Xamarin.iOS
    We have a "legacy" Xamarin.Android and Xamarin.iOS project. We would like to inject a Xamarin Forms component as a subview into a "native" Android and iOS view. The component is only available as a Xamarin Forms component and it is too expensive rewrite the entire app to Xamarin.Forms. The main question is how can we add complex Xamarin.Forms layouts as a subview in a "native" Xamarin.Android or Xamarin.iOS view? We have done some proof of concept work, and have successfully injected a XF third party component as a single Xamarin Forms element. However, this technique does not fully work when