diff options
author | E.Z. Hart <hartez@users.noreply.github.com> | 2016-04-06 21:46:01 -0600 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-04-06 20:46:01 -0700 |
commit | 4abf6102bcaac48e0853e5a30249c6ea1538f4b5 (patch) | |
tree | 37a320ace0c1a416474fe49f2f6fbd9e3c63f78c | |
parent | ab0cd64ba5dd3cde58700c50e27c00f812d18d96 (diff) | |
download | xamarin-forms-4abf6102bcaac48e0853e5a30249c6ea1538f4b5.tar.gz xamarin-forms-4abf6102bcaac48e0853e5a30249c6ea1538f4b5.tar.bz2 xamarin-forms-4abf6102bcaac48e0853e5a30249c6ea1538f4b5.zip |
Fix race condition in IsInvokeRequired on Android
3 files changed, 67 insertions, 9 deletions
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 00000000..09192145 --- /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<Task> GenerateTasks() + { + var result = new List<Task>(); + + 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 e58378d2..f843a2e3 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 @@ <DependentUpon>Bugzilla38416.xaml</DependentUpon> </Compile> <Compile Include="$(MSBuildThisFileDirectory)InputTransparentIssue.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)IsInvokeRequiredRaceCondition.cs" /> <Compile Include="$(MSBuildThisFileDirectory)IsPasswordToggleTest.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Issue1025.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Issue1026.cs" /> diff --git a/Xamarin.Forms.Platform.Android/Forms.cs b/Xamarin.Forms.Platform.Android/Forms.cs index b2ded248..65bfbc4d 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) { |