mon*_*str 5 wpf user-interface block task
我已经使用了Task类型.一切都很好而Task没有任何回报.例如:
XAML:
<Button Name="_button"
Click="ButtonBase_OnClick">
Click
</Button>
Run Code Online (Sandbox Code Playgroud)
代码隐藏:
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));
});
}
Run Code Online (Sandbox Code Playgroud)
这很好用.但是我想要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;
}
Run Code Online (Sandbox Code Playgroud)
这里我们遇到了UI阻塞问题.UI线程被锁定,直到任务将返回结果.
_button.IsEnabled = false;
Run Code Online (Sandbox Code Playgroud)
因此,上面的字符串完全被忽略.我在.Net 4.0,所以我不能使用async/await方法.这个问题真的让我感到恶心......有解决方案吗?
你的主线程阻塞,因为调用Task.Result等待直到Task完成.相反,你可以使用Task.ContinueWith()访问Task.Result 后的Task已完成.调用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());
}
Run Code Online (Sandbox Code Playgroud)
更新
如果您使用的是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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3364 次 |
| 最近记录: |