C# 后台工作开始完成时弹出菜单中出现错误?

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.

我正在构建一个通用应用程序,我想我在Windows Phone 8.1弹出菜单控件中发现了一个bug。我已经能够用一小段代码重现它。它在Windows 8上运行良好,但在Windows Phone 8.1上不起作用

每当我从按钮中创建弹出菜单时,当后台任务正在运行时,它不会从ShowFromSelectionSync返回?为什么? 同样的代码也适用于Windows8

我发现我的应用程序有很多后台工作要做,所以这个控件在手机上不能正常工作了。有什么建议可以解决这个问题吗

我有一个MainPage.xaml:

<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");
}