子窗口中的任务暂停UI

时间:2014-09-09 12:18:57

标签: c# wpf multithreading xaml task

我有AuthenticateWindowMainWindow,标记和代码在下面公开。它非常简化。在MainWindow构造函数中,我使用Thread类时,它可以正常工作,但如果我使用Task类,则会暂停UI,即“MainWindow”' Thread.Sleep(5000);过去时未显示。是否可以使用Task类(因为我需要它的取消机制和Status属性)而没有任何UI挂起?

重要条件:我无法修复AuthWindow中的代码。

AuthenticateWindow:

XAML

<Grid>
    <Button Content="OpenMainWindow"
            Click="ButtonBase_OnClick"></Button>
</Grid>

C#

public partial class AuthWindow : Window
{
    public AuthWindow()
    {
        InitializeComponent();
    }

    private void DoAbsolutelyNothing()
    {

    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(DoAbsolutelyNothing).ContinueWith(t =>
        {
            var window = new MainWindow();
            if (window.IsInitialized)
                window.Show();

            Close();
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}

主窗口:

XAML

<Grid>
    <TextBlock Text="MainWindow"></TextBlock>
</Grid>

C#

public partial class MainWindow : Window
{
    private Task _task;

    private void TestMethod()
    {
        Thread.Sleep(5000);
        Debug.WriteLine("TestMethod comleted");
    }

    public MainWindow()
    {
        InitializeComponent();

        // it works badly  
        //_task = Task.Factory.StartNew(TestMethod);

        // it works fine
        new Thread(TestMethod).Start();
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {

    }
}

Windows 7,.Net 4.0

重要说明:公开的代码会重现问题,只需复制粘贴!

2 个答案:

答案 0 :(得分:3)

您必须强制任务在另一个线程上运行

Task.Factory.StartNew(TestMethod, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);

更多信息:
Why Starting A New Task In The Task Parallel Library (TPL) Doesn’t Always Start A New Thread

答案 1 :(得分:1)

TaskScheduler.FromCurrentSynchronizationContext()不在ThreadPool同步上下文中创建任务,但在上下文中调用它,在这种情况下从UI调用,这就是它被冻结的原因。