summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsInvokeRequiredRaceCondition.cs65
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
-rw-r--r--Xamarin.Forms.Platform.Android/Forms.cs10
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)
{