Aym*_*udi 0 .net c# events asynchronous async-await
这个问题在某种程度上被问到了很多线程,但我找不到一个明确的答案我的情况,我有一个简单的代码,a Button,a Textbox和a ButtonClickEventHandler,后者尽管是这样Async,保持UI阻塞,代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Task t = new Task(() =>
{
for (int i = 0; i < 10000; i++)
{
Dispatcher.Invoke((()=>
{
TextBox.Text += i.ToString();
}));
}
});
t.Start();
await t;
//Something else
}
}
Run Code Online (Sandbox Code Playgroud)
Xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Margin="180,10,185,277" x:Name="Button" Click="ButtonBase_OnClick">
Ok
</Button>
<TextBox Margin="29,83,40,33" x:Name="TextBox"></TextBox>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
首先,为什么会发生这种情况?其次,我应该做些什么来使UI保持正常工作而不会挂起,总是遵循这个逻辑.
定义"阻止".您发布的代码不会阻止UI.但它肯定会让它真的很忙,这可能会让它看起来好像被阻挡了.就此而言,即使不是真的,也要阻止它用于所有实际目的.
您基本上是在GUI线程上执行拒绝服务攻击.你有一个紧密循环的辅助线程,只是继续在GUI线程上执行东西.不要这样做,事情会好得多.
正如其他人所指出的,如果您过于频繁地尝试更新UI,最终会阻止用户交互.
至于你的代码,你应该使用Task.Run而不是任务构造函数,而IProgress<T>不是Dispatcher.Invoke.我有一个IProgress<T>实现为您处理限制,可以这样使用:
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
using (var progress = ObservableProgress<int>.CreateForUi(value => UpdateUi(value)))
{
await Task.Run(() => BackgroundOperation(progress));
}
...
}
private static void UpdateUi(int progressUpdate)
{
TextBox.Text += progressUpdate.ToString();
}
private static void BackgroundOperation(IProgress<int> progress)
{
for (int i = 0; i < 10000; i++)
{
if (progress != null)
progress.Update(i);
}
}
Run Code Online (Sandbox Code Playgroud)
不需要人工延迟.
| 归档时间: |
|
| 查看次数: |
179 次 |
| 最近记录: |