异步编程的艺术:C# 中命令执行与Winform界面交互的完美融合
				
									
					
					
						|  | 
							admin 2025年3月14日 9:44
								本文热度 2000 | 
					
				 
				CommunityToolkit.Mvvm提供了强大的异步编程支持,通过IAsyncRelayCommand和AsyncRelayCommand等类型,使得在MVVM架构中处理异步操作变得简单而优雅。本文将详细介绍如何在WinForm应用中使用这些特性。
核心组件
主要异步命令类型
- IAsyncRelayCommand
- AsyncRelayCommand
- AsyncRelayCommand
异步命令特性
实战示例
基础项目设置
首先创建一个WinForm项目,添加必要的NuGet包:
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
 
示例ViewModel                
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
usingstatic System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace App13
{
    // ObservableObject 是 CommunityToolkit.Mvvm 提供的基础 ViewModel 类
    public partial class MainViewModel : ObservableObject
    {
        // 使用 ObservableProperty 特性自动实现属性通知
        [ObservableProperty]
        privatestring status = "就绪";
        [ObservableProperty]
        privatebool isLoading;
        // 异步命令 - 基础示例
        private readonly IAsyncRelayCommand loadDataCommand;
        public IAsyncRelayCommand LoadDataCommand => loadDataCommand;
        public MainViewModel()
        {
            // 初始化异步命令
            loadDataCommand = new AsyncRelayCommand(LoadDataAsync);
        }
        // 模拟异步数据加载
        private async Task LoadDataAsync()
        {
            try
            {
                IsLoading = true;
                Status = "正在加载数据...";
                // 模拟耗时操作
                await Task.Delay(2000);
                Status = "数据加载完成!";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发生错误:{ex.Message}");
                Status = "加载失败";
            }
            finally
            {
                IsLoading = false;
            }
        }
    }
}
带取消功能的高级示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace App13
{
    public partial class AdvancedViewModel : ObservableObject
    {
        [ObservableProperty]
        privatestring progressStatus = "就绪";
        [ObservableProperty]
        privateint progressValue;
        // 使用 CancellationTokenSource 支持取消操作
        private CancellationTokenSource? cts;
        // 声明异步命令
        private readonly IAsyncRelayCommand startProcessCommand;
        private readonly IRelayCommand cancelCommand;
        public IAsyncRelayCommand StartProcessCommand => startProcessCommand;
        public IRelayCommand CancelCommand => cancelCommand;
        public AdvancedViewModel()
        {
            startProcessCommand = new AsyncRelayCommand(
                ExecuteLongProcessAsync,
                // 通过判断 cts 是否为 null 来确定命令是否可执行
                () => cts == null
            );
            cancelCommand = new RelayCommand(
                // 取消操作的实现
                () =>
                {
                    cts?.Cancel();
                    cts = null;
                },
                // 只有在进程运行时才能取消
                () => cts != null
            );
        }
        private async Task ExecuteLongProcessAsync()
        {
            try
            {
                // 创建新的 CancellationTokenSource
                cts = new CancellationTokenSource();
                ProgressStatus = "处理中...";
                ProgressValue = 0;
                // 模拟长时间运行的任务
                for (int i = 0; i <= 100; i += 10)
                {
                    // 检查是否请求取消
                    cts.Token.ThrowIfCancellationRequested();
                    ProgressValue = i;
                    await Task.Delay(500, cts.Token);
                }
                ProgressStatus = "处理完成!";
                ProgressValue = 100;
            }
            catch (OperationCanceledException)
            {
                ProgressStatus = "操作已取消";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发生错误:{ex.Message}");
                ProgressStatus = "处理失败";
            }
            finally
            {
                cts = null;
                // 通知命令可用性变化
                (StartProcessCommand as AsyncRelayCommand)?.NotifyCanExecuteChanged();
                (CancelCommand as RelayCommand)?.NotifyCanExecuteChanged();
            }
        }
    }
}
WinForm界面实现
namespace App13
{
    public partial class Form1 : Form
    {
        private readonly MainViewModel viewModel;
        private readonly AdvancedViewModel advancedViewModel;
        public Form1()
        {
            InitializeComponent();
            // 初始化ViewModel
            viewModel = new MainViewModel();
            advancedViewModel = new AdvancedViewModel();
            // 设置数据绑定
            SetupDataBindings();
        }
        private void SetupDataBindings()
        {
            // 基础示例绑定
            btnLoad.Click += async (s, e) => await viewModel.LoadDataCommand.ExecuteAsync(null);
            // 使用BindingSource实现属性绑定
            var bindingSource = new BindingSource();
            bindingSource.DataSource = viewModel;
            lblStatus.DataBindings.Add("Text", bindingSource, nameof(viewModel.Status));
            // 高级示例绑定
            btnStart.Click += async (s, e) => await advancedViewModel.StartProcessCommand.ExecuteAsync(null);
            btnCancel.Click += (s, e) => advancedViewModel.CancelCommand.Execute(null);
            var advancedBindingSource = new BindingSource();
            advancedBindingSource.DataSource = advancedViewModel;
            progressBar.DataBindings.Add("Value", advancedBindingSource, nameof(advancedViewModel.ProgressValue));
            lblProgressStatus.DataBindings.Add("Text", advancedBindingSource, nameof(advancedViewModel.ProgressStatus));
        }
    }
}

总结
CommunityToolkit.Mvvm提供的异步支持极大地简化了WinForm应用中的异步操作处理。通过AsyncRelayCommand和相关组件,我们可以:
- 优雅地处理异步操作
- 轻松实现取消功能
- 有效管理UI状态
- 提供良好的用户体验
合理使用这些特性,可以显著提高应用程序的响应性和用户体验。
该文章在 2025/3/14 9:44:27 编辑过