WPF 一个执行耗时任务,页面更新等待时间的例子

xaml页面,一个按钮,一个lable,lable用来更新等待的时间。点击按钮,每过1秒,label的数值+1,直到任务结束。

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" Margin="350,0,0,0" VerticalAlignment="Center" Height="72" Width="149" Click="Button_Click"/>
        <Label Content="0" HorizontalAlignment="Left" Margin="350,281,0,0" VerticalAlignment="Top"  x:Name="Lab"/>

    </Grid>
</Window>

.cs代码

 private async void Button_Click(object sender, RoutedEventArgs e)
 {
     bool isOk = false;
     Wait((result)=>isOk = result);
     while (!isOk)
     {
         //等待耗时任务结束,界面的Label加1
         await Task.Delay(1000);
         Lab.Content = Convert.ToInt32(Lab.Content) + 1;
     }
 }

 private async void Wait(Action<bool> callback)
 {
     bool isok = false;
     //耗时任务
     for (int i = 0; i < 10; i++)
     {
         await Task.Delay(1000);
     }
     isok = true;
     callback?.Invoke(isok);
 }

### 如何在 WPF 中安全地从非 UI 线程更新 TextBox 控件 为了确保线程安全性,在 WPF 应用程序中应当通过 `Dispatcher` 对象来执行来自非 UI 线程的操作。这是因为 WPFUI 组件不是线程安全的,只有创建它们的那个特定线程可以访问和修改这些组件。 当需要在一个后台工作线程上完成某些处理并希望随后更新 UI 上的一个 `TextBox` 或其他任何控件时,应该使用该控件所属窗口或应用程序主线程所提供的调度器服务来进行跨线程调用[^1]。 下面是一个简单的例子展示如何利用 C# 和 XAML 来实现这一点: #### 使用 Dispatcher.Invoke 方法更新 TextBox 文本 ```csharp private void UpdateTextBoxFromNonUIThread(string newText) { if (textBox.Dispatcher.CheckAccess()) { textBox.Text = newText; } else { textBox.Dispatcher.Invoke(() => { textBox.Text = newText; }); } } ``` 这段代码首先检查当前线程是否有权限直接操作 `TextBox`(即是否为 UI 线程)。如果不是,则它会安排一个回调函数运行于拥有此控件所有权的线程上下文中——通常是应用的主要消息循环所在的线程。这样就保证了即使是从另一个线程发起请求也能正确无误地改变界面上的文字显示[^2]。 另外一种更简洁的方式是在 .NET Framework 4.5 及以上版本中使用 `async/await` 关键字配合 `Task.Run()` 启动异步任务,并在其内部等待返回至 UI 线程再做进一步交互[^3]: #### 使用 async/await 模式简化多线程编程 ```csharp private async Task PerformBackgroundOperationAsync() { string result = await Task.Run(() => DoSomeWork()); // 返回到 UI 线程继续执行 textBox.Text = result; } // 假设这是模拟耗时工作的简单方法 private string DoSomeWork() { Thread.Sleep(2000); return "已完成"; } ``` 这种方法不仅提高了可读性和维护性,还减少了手动管理线程同步带来的复杂度。对于现代开发而言推荐采用这种方式来处理涉及长时间计算的任务以及随之而来的 UI 刷新逻辑[^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

orangapple

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值