gpt4 book ai didi

WPF 异步 Task 阻塞 UI

转载 作者:行者123 更新时间:2023-12-04 17:34:52 27 4
gpt4 key购买 nike

我已经与 Task 合作过类型。一切都很好,同时 Task什么都不回。例如:

XAML:

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

代码隐藏:
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方法。
这个问题真的让我恶心……有解决方案吗?

最佳答案

您的主线程被阻塞,因为调用 Task.Result等到Task已经完成。相反,您可以使用 Task.ContinueWith()访问 Task.ResultTask已经完成。调用 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;
}

关于WPF 异步 Task<T> 阻塞 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23934236/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com