1

我有这个 xaml

<Window x:Class="TestCloseWindow.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Width="500" Height="400">
<StackPanel>
    <TextBlock x:Name="Seconds"></TextBlock>
    <Button Content="fasdfd" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Window>

而这段代码

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
         await CountToTen();
    }

    private Task CountToTen()
    {
       return Task.Factory.StartNew
              (() =>
                  {
                      for (var i = 1; i <= 10; i++)
                      {
                        Seconds.Text = i.ToString(CultureInfo.InvariantCulture);
                        Task.Delay(1000).Wait();
                      }
                   }
                   , CancellationToken.None
                   , TaskCreationOptions.None
                   , TaskScheduler.FromCurrentSynchronizationContext()
              );
    }
}

在这段代码中,我使用 TaskScheduler.FromCurrentSynchronizationContext() 来从后台任务访问 UI。
我希望我可以看到程序计数到 10,但不是它,而是我在 TextBlock 中看到 10 秒和 10 秒后的阻塞 UI

我该如何解决?

4

2 回答 2

2

Wait您正在CountToTen函数中使用阻塞调用。要解决此问题,您将需要await改用。这也需要一些其他的改变。

async private Task CountToTen()
{
    await Task.Factory.StartNew( async () =>
        {
            for (var i = 1; i <= 10; i++)
            {
                Seconds.Text = i.ToString(CultureInfo.InvariantCulture);
                //Task.Delay(1000).Wait();
                await Task.Delay(1000);
            }
        }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
于 2013-03-28T13:39:04.887 回答
0

通过使用StartNewwith TaskScheduler.FromCurrentSynchronizationContext(),在这种特殊情况下,您实际上并没有做任何事情。由于整个任务将在 UI 线程中运行,因此与直接在那里执行它没有什么不同。

您的问题的主要来源是Task.Delay(1000).Wait();. 您正在等待一秒钟,并且您正在从 UI thread执行此操作。您可以重构代码以不进行阻塞等待,还可以删除不必要的任务创建。这就是你所需要的:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    for (var i = 1; i <= 10; i++)
    {
        Seconds.Text = i.ToString(CultureInfo.InvariantCulture);
        await Task.Delay(1000)
    }
}
于 2013-04-09T15:59:18.870 回答