C# 后台工作开始完成时弹出菜单中出现错误?
我正在构建一个通用应用程序,我想我在Windows Phone 8.1弹出菜单控件中发现了一个bug。我已经能够用一小段代码重现它。它在Windows 8上运行良好,但在Windows Phone 8.1上不起作用 每当我从按钮中创建弹出菜单时,当后台任务正在运行时,它不会从ShowFromSelectionSync返回?为什么? 同样的代码也适用于Windows8 我发现我的应用程序有很多后台工作要做,所以这个控件在手机上不能正常工作了。有什么建议可以解决这个问题吗 我有一个MainPage.xaml:C# 后台工作开始完成时弹出菜单中出现错误?,c#,xaml,windows-phone-8.1,win-universal-app,C#,Xaml,Windows Phone 8.1,Win Universal App,我正在构建一个通用应用程序,我想我在Windows Phone 8.1弹出菜单控件中发现了一个bug。我已经能够用一小段代码重现它。它在Windows 8上运行良好,但在Windows Phone 8.1上不起作用 每当我从按钮中创建弹出菜单时,当后台任务正在运行时,它不会从ShowFromSelectionSync返回?为什么? 同样的代码也适用于Windows8 我发现我的应用程序有很多后台工作要做,所以这个控件在手机上不能正常工作了。有什么建议可以解决这个问题吗 我有一个MainPage.
<Page
x:Class="PopupMenuBugPhone.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PopupMenuBugPhone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Button Content="Test Bug" Click="Button_Click" />
</StackPanel>
</Grid>
</Page>
MainPage.xaml.cs:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var frameworkElement = sender as FrameworkElement;
var task = SimulateBackgroundWork(); // COMMENT THIS TO MAKE IT WORK ON PHONE!!!
var menu = new PopupMenu();
var сmdOption1 = new UICommand("Option1");
var cmdOption2 = new UICommand("Option2");
menu.Commands.Add(сmdOption1);
menu.Commands.Add(cmdOption2);
// We don't want to obscure content, so pass in a rectangle representing the sender of the context menu event.
var chosenCommand = await menu.ShowForSelectionAsync(frameworkElement.GetElementRect());
if (chosenCommand == null) // The command is null if no command was invoked.
{
await new MessageDialog("No choice").ShowAsync();
}
else
{
await new MessageDialog("Choice: " + chosenCommand.Label).ShowAsync();
}
await task; // COMMENT THIS TO MAKE IT WORK ON PHONE!!!
}
private Task SimulateBackgroundWork()
{
var t = Task.Run(() =>
{
var dt = DateTime.Now;
// Do some dummy processing loop
while (DateTime.Now < dt.AddSeconds(300))
{
;
}
});
return t;
}
}
使用MenuFlyout怎么样 假设您在页面的代码隐藏中定义了它,并使用TaskCompletionSource对其进行包装,以使显示成为可等待的:
MenuFlyout flyout = new MenuFlyout();
TaskCompletionSource<string> tcs;
ShowMenuFlyout是可以等待的,它的实现方式如下:
public Task<string> ShowMenuFlyout(FrameworkElement sender)
{
tcs = new TaskCompletionSource<string>();
flyout.ShowAt(sender as FrameworkElement);
return tcs.Task;
}
这在两种平台上都适用。当然,这只是概念的证明,您可能希望在此处或此处进行空检查,但它是有效的
public Task<string> ShowMenuFlyout(FrameworkElement sender)
{
tcs = new TaskCompletionSource<string>();
flyout.ShowAt(sender as FrameworkElement);
return tcs.Task;
}
async void mf_Click(object sender, RoutedEventArgs e)
{
flyout.Closed -= flyout_Closed;
await new MessageDialog("Choice: " + (sender as MenuFlyoutItem).Text).ShowAsync();
tcs.SetResult((sender as MenuFlyoutItem).Text);
}
async void flyout_Closed(object sender, object e)
{
flyout.Closed -= flyout_Closed;
await new MessageDialog("No choice").ShowAsync();
tcs.SetResult("No choice");
}