WPF异步Task<T>阻塞UI

7

我已经使用过Task类型。当Task不返回任何内容时,一切都很好。例如:

XAML:

<Button Name="_button"
        Click="ButtonBase_OnClick">
        Click
</Button>  

CodeBehind:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    _button.IsEnabled = false;

    Task.Factory.StartNew(() =>
    {
        Thread.Sleep(5*1000);
        Dispatcher.Invoke(new Action(() => _button.IsEnabled = true));
    });
}

这个工作正常。但是我想让 Task 返回一些值,例如 Boolean。因此我需要使用 Task<Boolean>

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    _button.IsEnabled = false;

    var task = Task<Boolean>.Factory.StartNew(() =>
    {
        Thread.Sleep(5*1000);
        return true;
    });

    if (task.Result)
        _button.IsEnabled = true;
}

这里涉及到UI阻塞的问题。UI线程会被锁定直到任务返回结果。

_button.IsEnabled = false;

那么,上面的字符串完全被忽略了。 我使用的是.Net 4.0,所以无法使用async/await方法。 这个问题真的让我很烦恼... 它有解决方案吗?


4
使用 Microsoft.Bcl.Async,你可以在 .net 4.0 中使用 async/await,使生活更加轻松:) - Sriram Sakthivel
1个回答

12
您的主线程正在阻塞,因为调用Task.Result会等待Task完成。相反,您可以使用Task.ContinueWith()Task完成后访问Task.Result。调用TaskScheduler.FromCurrentSynchronizationContext()会导致延续在主UI线程上运行(因此您可以安全地访问_button)。
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    _button.IsEnabled = false;

    Task<Boolean>.Factory.StartNew(() =>
    {
        Thread.Sleep(5*1000);
        return true;
    }).ContinueWith(t=>
    {
        if (t.Result)
            _button.IsEnabled = true;
    }, TaskScheduler.FromCurrentSynchronizationContext());        
}

更新

如果您正在使用C# 5,您可以使用async/await替代。

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    _button.IsEnabled = false;

    var result = await Task.Run(() =>
    {
        Thread.Sleep(5*1000);
        return true;
    });

    _button.IsEnabled = result;      
}

可以了,谢谢 :) 啊啊啊!为什么Herbert Scheldt在他的书中没有提到这个?你能给我关于任务的好信息来源吗?当然除了GoogleMSDN - monstr
1
MSDN拥有您所需的所有信息。请查看此处名为创建任务连续项的章节。链接 - Alex Wiese
1
很抱歉重新激活一个旧的问答,但当我遇到这个问题时,我发现你的回答和这个链接非常有帮助:http://blogs.msdn.com/b/csharpfaq/archive/2010/06/18/parallel-programming-task-schedulers-and-synchronization-context.aspx留在这里供参考! - matrixanomaly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接