WinForm 跨线程操作 UI 控件封装实践

188 阅读3分钟

C# WinForm 跨线程操作 UI 控件封装实践

前言

在使用 C# 开发 WinForm 窗体应用程序时,经常会遇到需要在多线程中处理耗时任务的场景。然而,在多线程中直接操作 UI 控件会引发异常:“跨线程操作无效”

为了解决这个问题,通常的做法是通过委托(Delegate)实现线程安全的 UI 操作。为了提高开发效率和代码复用性,我将常用的几种控件(如 TextBox、Label、CheckBox、RadioButton、ProgressBar)的操作进行了封装,方便后续项目中的调用。

本文将介绍该封装类的设计思路与使用方法,并附上部分核心源码供参考。

正文

1、使用示例

以下是在实际窗体程序中对 TextBox 控件进行设置和获取值的使用方式:

// 引入命名空间
using XY.WINUI.ControlEx.InvokeEx;

// 第一种调用方式:通过 Invokes 类统一调用
Invokes.SetTextBoxText(tbName, "TextBox文本");
string value = Invokes.GetTextBoxText(tbName);

// 第二种调用方式:通过具体控件类调用
TextBoxInvoke.SetTextBoxText(tbName, "TextBox文本");
string value = TextBoxInvoke.GetTextBoxText(tbName);

上述两种方式可以任选其一,前者适用于集中管理多个控件操作,后者则更直观清晰。

类似地,其他控件也提供了对应的封装方法,例如:

  • Label:SetLabelText() / GetLabelText()

  • RadioButton:SetRadioButtonChecked() / GetRadioButtonChecked()

  • CheckBox:SetCheckBoxChecked() / GetCheckBoxChecked()

  • ProgressBar:SetProgressBarValue() / GetProgressBarValue()

2、封装类设计与实现

所有封装类都位于 XY.WINUI.ControlEx.InvokeEx 命名空间下,其中 Invokes.cs 是一个集合类,用于对外提供统一接口。

Invokes.cs 核心代码节选如下:
using System;
using System.Windows.Forms;

namespace XY.WINUI.ControlEx.InvokeEx
{
    public class Invokes
    {
        #region // TextBox
        public static void SetTextBoxText(TextBox Ctrl, string Text)
        {
            TextBoxInvoke.SetTextBoxText(Ctrl, Text);
        }

        public static string GetTextBoxText(TextBox Ctrl)
        {
            return TextBoxInvoke.GetTextBoxText(Ctrl); ;
        }
        #endregion

        #region // Label
        public static void SetLabelText(Label Ctrl, string Text)
        {
            LabelInvoke.SetLabelText(Ctrl, Text);
        }

        public static string GetLabelText(Label Ctrl)
        {
            return LabelInvoke.GetLabelText(Ctrl); ;
        }
        #endregion 

        // 其他控件封装省略...

        #region // Common - Visible 操作
        private delegate bool GetControlVisibleDelegate(Control Ctrl);
        private delegate void SetControlVisibleDelegate(Control Ctrl, bool Visible);

        private static bool GetControlVisibleFunc(Control Ctrl)
        {
            return Ctrl.Visible;
        }

        public static bool GetControlVisible(Control Ctrl)
        {
            return (bool)Ctrl.Invoke(new GetControlVisibleDelegate(GetControlVisibleFunc), new object[] { Ctrl });
        }

        private static void SetControlVisibleFunc(Control Ctrl, bool Visible)
        {
            Ctrl.Visible = Visible;
            Ctrl.Refresh();
        }

        public static void SetControlVisible(Control Ctrl, bool Visible)
        {
            Ctrl.Invoke(new SetControlVisibleDelegate(SetControlVisibleFunc), new object[] { Ctrl, Visible });
        } 
        #endregion
    }
}

⚠️ 注意:以上代码仅展示部分内容,完整代码可在 GitHub 仓库 中查看,路径为:XY.WINUI.ControlEx.InvokeEx 文件夹。

3. 测试界面

以下是测试窗体运行时的截图,展示了不同控件的使用效果:

总结

本文介绍了如何通过封装委托方式解决 C# WinForm 中常见的跨线程操作 UI 控件问题。通过封装常用控件的方法,提高了代码的可读性和复用性,同时也简化了开发在实际项目中的调用流程。

本封装库目前支持多种基础控件的线程安全操作,未来将持续更新并完善更多功能。

欢迎访问 GitHub 仓库参与补充或改进:XY.WINUI GitHub 地址

关键词

C#, WinForm, 跨线程操作, UI 控件, 委托, 封装类, TextBox, Label, CheckBox, RadioButton, ProgressBar, GitHub, 多线程, 线程安全, 控件封装

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:CodeHsu

出处:cnblogs.com/seayxu/p/5523026.html

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!