[WinRT] Use a queue to prevent multiple MessageDialogs from causing a crash (#347)

* [WinRT] Use a queue to prevent multiple MessageDialogs from causing a crash

* Make change to use Device.IsInvokeRequired
This commit is contained in:
Paul DiPietro 2016-12-16 09:58:47 -06:00 коммит произвёл Rui Marinho
Родитель 3716c57aab
Коммит db4486db8f
3 изменённых файлов: 73 добавлений и 2 удалений

Просмотреть файл

@ -0,0 +1,37 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System;
using System.Threading.Tasks;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Bugzilla, 43469, "Calling DisplayAlert twice in WinRT causes a crash", PlatformAffected.WinRT)]
public class Bugzilla43469 : TestContentPage
{
protected override void Init()
{
var button = new Button { Text = "Click to call DisplayAlert twice" };
button.Clicked += (sender, args) =>
{
Device.BeginInvokeOnMainThread(new Action(async () =>
{
await DisplayAlert("First", "Text", "Cancel");
}));
Device.BeginInvokeOnMainThread(new Action(async () =>
{
await DisplayAlert("Second", "Text", "Cancel");
}));
};
Content = button;
}
}
}

Просмотреть файл

@ -131,6 +131,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42364.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42519.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla43313.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla43469.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla43516.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla43663.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44944.cs" />

Просмотреть файл

@ -761,8 +761,41 @@ namespace Xamarin.Forms.Platform.WinRT
dialog.CancelCommandIndex = (uint)dialog.Commands.Count - 1;
}
IUICommand command = await dialog.ShowAsync();
options.SetResult(command.Label == options.Accept);
if (Device.IsInvokeRequired)
{
Device.BeginInvokeOnMainThread(async () =>
{
IUICommand command = await dialog.ShowAsyncQueue();
options.SetResult(command.Label == options.Accept);
});
}
else
{
IUICommand command = await dialog.ShowAsyncQueue();
options.SetResult(command.Label == options.Accept);
}
}
}
// refer to http://stackoverflow.com/questions/29209954/multiple-messagedialog-app-crash for why this is used
// in order to allow for multiple MessageDialogs, or a crash occurs otherwise
public static class MessageDialogExtensions
{
static TaskCompletionSource<MessageDialog> _currentDialogShowRequest;
public static async Task<IUICommand> ShowAsyncQueue(this MessageDialog dialog)
{
while (_currentDialogShowRequest != null)
{
await _currentDialogShowRequest.Task;
}
var request = _currentDialogShowRequest = new TaskCompletionSource<MessageDialog>();
var result = await dialog.ShowAsync();
_currentDialogShowRequest = null;
request.SetResult(dialog);
return result;
}
}
}