From 4abf6102bcaac48e0853e5a30249c6ea1538f4b5 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Wed, 6 Apr 2016 21:46:01 -0600 Subject: [PATCH] Fix race condition in IsInvokeRequired on Android --- .../IsInvokeRequiredRaceCondition.cs | 65 ++++++++++++++++++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 1 + Xamarin.Forms.Platform.Android/Forms.cs | 10 +--- 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsInvokeRequiredRaceCondition.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsInvokeRequiredRaceCondition.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsInvokeRequiredRaceCondition.cs new file mode 100644 index 0000000..0919214 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsInvokeRequiredRaceCondition.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Xamarin.Forms.CustomAttributes; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +#endif + + +namespace Xamarin.Forms.Controls +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.None, 0, "Device.IsInvokeRequired race condition causes crash")] + public class IsInvokeRequiredRaceCondition : TestContentPage + { + protected override void Init() + { + var button = new Button + { + AutomationId = "crashButton", + Text = "Start Test" + }; + + var success = new Label { Text = "Success", IsVisible = false, AutomationId = "successLabel" }; + + var instructions = new Label { Text = "Click the Start Test button. " }; + + Content = new StackLayout + { + HorizontalOptions = LayoutOptions.Fill, + VerticalOptions = LayoutOptions.Fill, + Children = { instructions, success, button } + }; + + button.Clicked += async (sender, args) => + { + await Task.WhenAll(GenerateTasks()); + success.IsVisible = true; + }; + } + + List GenerateTasks() + { + var result = new List(); + + for (int n = 0; n < 1000; n++) + { + result.Add(Task.Run(() => { var t = Device.IsInvokeRequired; } )); + } + + return result; + } + +#if UITEST + [Test] + public void ShouldNotCrash() + { + RunningApp.Tap(q => q.Marked("crashButton")); + RunningApp.WaitForElement(q => q.Marked("successLabel")); + } +#endif + + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index e58378d..f843a2e 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -99,6 +99,7 @@ Bugzilla38416.xaml + diff --git a/Xamarin.Forms.Platform.Android/Forms.cs b/Xamarin.Forms.Platform.Android/Forms.cs index b2ded24..65bfbc4 100644 --- a/Xamarin.Forms.Platform.Android/Forms.cs +++ b/Xamarin.Forms.Platform.Android/Forms.cs @@ -362,15 +362,7 @@ namespace Xamarin.Forms return new _IsolatedStorageFile(IsolatedStorageFile.GetUserStoreForApplication()); } - public bool IsInvokeRequired - { - get - { - using (Looper my = Looper.MyLooper()) - using (Looper main = Looper.MainLooper) - return my != main; - } - } + public bool IsInvokeRequired => !Looper.MainLooper.IsCurrentThread; public void OpenUriAction(Uri uri) { -- 2.7.4