WPF异步任务阻止UI

XAML:

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

CS

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;

最佳答案

您的主线程正在阻塞,因为对Task.Result的调用将等待,直到Task完成.相反,您可以在Task完成后使用Task.ContinueWith()访问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.

async/await 的解决方案刚好解决了当前我遇到的问题,因为异步使用了等待结果返回,所以导致UI卡死状态,

原文地址:https://codeday.me/bug/20190528/1173806.html

发布了18 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_28368039/article/details/90665330