63.网页请求与按钮禁用 C#例子 WPF例子
这是一个简单的从网页获得一些数据的代码,使用了按钮禁用功能防止连续点击。使用了Dispatcher.Invoke从UI线程更新。使用了throw丢出异常。
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
TextBlock2.Text = $"错误:{ex.Message}";
});
使用 Dispatcher.Invoke
来更新 UI,显示异常消息。这是正确的做法,因为您不能在非 UI 线程上直接更新 WPF UI 元素。
try
{
data = await httpclient.GetStringAsync(url);
}
catch(Exception ex)
{
throw new InvalidOperationException(ex.Message);
}
先说结论,这里catch捕捉到的错误会被重新丢出,被调用这个函数的外部的catch重新捕捉。
当然,让我们更详细地解释throw new InvalidOperationException(ex.Message);
这行代码中的每一个部分:
throw
关键字:throw
是C#中的一个关键字,用于显式地抛出一个异常。当执行到throw
语句时,当前方法的执行将立即停止,并且控制权将转移到调用栈中最近的catch
块(如果存在的话)。
new InvalidOperationException(...)
:- 这部分代码创建了一个新的
InvalidOperationException
实例。InvalidOperationException
是.NET框架中的一个异常类,通常用于指示在对象处于不适当的状态时调用的方法。例如,如果尝试在一个未初始化的对象上调用方法,或者尝试执行一个在当前上下文中无效的操作,就可能抛出此异常。 new
关键字用于创建对象的实例。在这里,它创建了一个InvalidOperationException
的新实例。
- 这部分代码创建了一个新的
(ex.Message)
:- 这是传递给
InvalidOperationException
构造函数的参数。ex
是之前catch
块中捕获的异常对象,而ex.Message
获取了该异常的消息文本。这个消息通常描述了导致异常发生的具体原因。 - 在这个上下文中,新抛出的
InvalidOperationException
将包含与原始异常相同的消息文本。这意味着虽然异常的类型改变了,但描述异常原因的信息被保留了下来。
- 这是传递给
<TextBlock x:Name="TextBlock1" Grid.Row="1" Text="waitting" TextWrapping="NoWrap"/>
<TextBlock x:Name="TextBlock2" Grid.Row="2" Text="waitting" TextWrapping="Wrap"/>
Wrap表示超出长度后会自动换行
首先,“wrap”在英文中意为“包裹”或“缠绕”,这个动作本身就包含了一种“围绕”或“覆盖”的意象。在计算机科学和编程领域,当文本内容超出其显示容器的宽度时,为了保持文本的完整性和可读性,就需要将文本内容换行到下一行。这个过程与“包裹”或“缠绕”的意象相似,因为文本被“包裹”或“缠绕”到了新的行中。
完整代码:
using System.Net.Http;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace 网页请求与按钮禁用
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
HttpClient httpclient = new HttpClient();
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
Button1.IsEnabled = false; // 禁用按钮以防止重复点击
try
{
// 调用异步方法 WebDataAsync,等待其完成
await WebDataAsync();
}
catch (Exception ex) // 捕获从 WebDataAsync 抛出的任何异常
{
// 使用 Dispatcher 在 UI 线程上更新 TextBlock2 的文本
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
TextBlock2.Text = $"错误:{ex.Message}"; // 显示异常消息
});
}
Button1.IsEnabled = true; // 重新启用按钮
}
public async Task WebDataAsync()
{
// 注意:这里使用了正确的 URL 格式,包含 http:// 协议
string url = "http://www.baidu.com";
//string url = "www.baidu.com"; // 这行被注释掉了,是正确的做法,因为缺少协议会导致异常
string data;
try
{
// 异步请求数据
data = await httpclient.GetStringAsync(url);
}
catch (Exception ex) // 捕获从 httpclient.GetStringAsync 抛出的任何异常
{
// 抛出一个新的 InvalidOperationException
throw new InvalidOperationException(ex.Message);
}
// 使用 Dispatcher 在 UI 线程上更新 TextBlock1 的文本
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
//这里的data不需要检查是否为空,因为如果不为空,说明try块没有发生错误。如果为空,那么catch块会丢出一个错误,这段代码不会被执行
TextBlock1.Text = $"头100个字符是:{(data.Length > 100 ? data.Substring(0, 100) + "..." : data)}";
});
}
}
}
<Window x:Class="网页请求与按钮禁用.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:网页请求与按钮禁用"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="Button1" Content="Button" HorizontalAlignment="Left" Margin="63,25,0,0" VerticalAlignment="Top" Click="Button_Click"/>
<TextBlock x:Name="TextBlock1" Grid.Row="1" Text="waitting" TextWrapping="Wrap"/>
<TextBlock x:Name="TextBlock2" Grid.Row="2" Text="waitting" TextWrapping="Wrap"/>
</Grid>
</Window>