C#多线程异步执行和跨线程访问控件Helper

 更新时间:2022年04月24日 08:36:35   作者:農碼一生  
这篇文章介绍了C#多线程异步执行和跨线程访问控件Helper,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、工具类代码

    public class TaskHelper
    {

        #region 多线程操作
        /// <summary>
        /// 功能描述:多线程执行方法,方法无参数,无返回值
        /// </summary>
        /// <param name="func">方法,如果方法中调用了控件,请使用 ThreadInvokerControl(() => { 您的操作})进行包括</param>
        /// <param name="callback">执行完成回调,参数为object,如果错误返回的是Exception,否则为null,如果为空则默认调用基类回调方法</param>
        /// <param name="enableControl">调用线程时禁用的控件</param>
        public static void TaskRun(
          Form frm,
          Func<Task> func,
          Action<object> callback = null,
          Control[] enableControl = null)
        {
            if (enableControl != null)
            {
                SetControlEnableds(enableControl, false);
            }

            Task.Factory.StartNew(() =>
            {
                try
                {
                    Task task = func();
                    if (task.Exception != null && task.Exception.InnerException != null)
                        throw task.Exception.InnerException;
                    callback?.Invoke(null);
                }
                catch (Exception ex)
                {
                    if (callback != null)
                        callback(ex);
                    else
                        ThreadBaseCallBack(frm, ex);
                }
                finally
                {
                    if (enableControl != null && frm != null)
                        ThreadInvokerControl(frm, () => { SetControlEnableds(enableControl, true); });
                }
            });
        }

        /// <summary>
        /// 功能描述:线程默认回调方法
        /// </summary>
        public static void ThreadBaseCallBack(Form frm, Exception ex)
        {
            if (frm != null)
            {
                ThreadInvokerControl(frm, () =>
                {
                    try
                    {
                        Exception lastEx = ex.GetOriginalException();
                        MessageBox.Show(lastEx.Message);
                    }
                    catch
                    {

                    }
                });
            }
        }

        /// <summary>
        /// 功能描述:委托调用,用于夸线程访问控件
        /// </summary>
        /// <param name="action">action</param>
        /// <param name="f">所在窗体,默认使用当前窗体</param>
        public static void ThreadInvokerControl(Form frm, Action action)
        {
            if (frm != null)
            {
                if (frm.InvokeRequired)
                {
                    frm.BeginInvoke(action);
                }
                else
                {
                    action();
                }
            }
        }

        #endregion

        #region 提示层
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        private static void ShowProcessPanel(Control parent, string strMessage)
        {
            if (parent.InvokeRequired)
            {
                parent.BeginInvoke(new MethodInvoker(delegate
                {
                    ShowProcessPanel(parent, strMessage);
                }));
            }
            else
            {
                parent.VisibleChanged -= new EventHandler(parent_VisibleChanged);
                parent.VisibleChanged += new EventHandler(parent_VisibleChanged);
                parent.FindForm().FormClosing -= ControlHelper_FormClosing;
                parent.FindForm().FormClosing += ControlHelper_FormClosing;
                Control control = null;
                lock (parent)
                {
                    control = HaveProcessPanelControl(parent);
                    if (control == null)
                    {
                        control = CreateProgressPanel();
                        parent.Controls.Add(control);
                    }
                }
                FWaiting fWaiting = control.Tag as FWaiting;
                fWaiting.Message = strMessage;
                fWaiting.Show();
            }
        }
        private static void ControlHelper_FormClosing(object sender, FormClosingEventArgs e)
        {
            Control control = sender as Control;
            control.FindForm().FormClosing -= ControlHelper_FormClosing;
            CloseWaiting(control);
        }

        private static void parent_VisibleChanged(object sender, EventArgs e)
        {
            Control control = sender as Control;
            control.VisibleChanged -= new EventHandler(parent_VisibleChanged);
            if (!control.Visible)
            {
                CloseWaiting(control);
            }
        }
        private static void CloseWaiting(Control control)
        {
            Control[] array = control.Controls.Find("myProgressPanelext", false);
            if (array.Length > 0)
            {
                Control myProgress = array[0];
                if (myProgress.Tag != null && myProgress.Tag is FWaiting)
                {
                    FWaiting fWaiting = myProgress as FWaiting;
                    if (fWaiting != null && !fWaiting.IsDisposed && fWaiting.Visible)
                    {
                        fWaiting.Hide();
                    }
                }
            }
        }
        private static void CloseProcessPanel(Control parent)
        {
            if (parent.InvokeRequired)
            {
                parent.BeginInvoke(new MethodInvoker(delegate
                {
                    CloseProcessPanel(parent);
                }));
            }
            else if (parent != null)
            {
                Control control = HaveProcessPanelControl(parent);
                if (control != null)
                {
                    Form frm = control.Tag as Form;
                    if (frm != null && !frm.IsDisposed && frm.Visible)
                    {
                        if (frm.InvokeRequired)
                        {
                            frm.BeginInvoke(new MethodInvoker(delegate
                            {
                                frm.Hide();
                            }));
                        }
                        else
                        {
                            frm.Hide();
                        }
                    }
                }
            }
        }
        private static Control HaveProcessPanelControl(Control parent)
        {
            Control[] array = parent.Controls.Find("myProgressPanelext", false);
            Control result;
            if (array.Length > 0)
            {
                result = array[0];
            }
            else
            {
                result = null;
            }
            return result;
        }
        private static Control CreateProgressPanel()
        {
            return new Label
            {
                Name = "myProgressPanelext",
                Visible = false,
                Tag = new FWaiting
                {
                    TopMost = true,
                }
            };
        }
        #endregion

        #region 禁用控件时不改变空间颜色
        [System.Runtime.InteropServices.DllImport("user32.dll ")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int wndproc);
        [System.Runtime.InteropServices.DllImport("user32.dll ")]
        private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        private const int GWL_STYLE = -16;
        private const int WS_DISABLED = 0x8000000;

        /// <summary>
        /// 功能描述:设置控件的Enable属性,控件不改颜色
        /// </summary>
        /// <param name="c">c</param>
        /// <param name="enabled">enabled</param>
        private static void SetControlEnabled(Control c, bool enabled)
        {
            if (enabled)
            {
                SetWindowLong(c.Handle, GWL_STYLE, (~WS_DISABLED) & GetWindowLong(c.Handle, GWL_STYLE));
            }
            else
            {
                SetWindowLong(c.Handle, GWL_STYLE, WS_DISABLED + GetWindowLong(c.Handle, GWL_STYLE));
            }
        }

        /// <summary>
        /// 功能描述:设置多个控件的Enable属性,控件不改颜色
        /// </summary>
        /// <param name="cs">cs</param>
        /// <param name="enabled">enabled</param>
        private static void SetControlEnableds(Control[] cs, bool enabled)
        {
            foreach (var c in cs)
            {
                SetControlEnabled(c, enabled);
            }
        }
        #endregion
    }

二、调用代码

            TaskHelper.TaskRun(this, async () =>
            {
                TaskHelper.ThreadInvokerControl(this, () =>
                {
                    //夸线程访问控件的
                    this.btnStart.Enabled = true;
                    this.btnStart.BackColor = Color.Gainsboro;
                });
            });

到此这篇关于C#多线程异步执行和跨线程访问控件Helper的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 利用C#在PDF文档中添加电子签名的实现流程

    利用C#在PDF文档中添加电子签名的实现流程

    电子签名在文档合规性与安全性保障中扮演着重要角色,基于 C# 开发 PDF 电子签名功能是企业级文档处理场景的常见需求,Spire.PDF for .NET 作为国产 PDF 处理类库,无需依赖 Adobe Acrobat 等第三方软件,即可便捷实现 PDF 电子签名添加,本文为大家详细介绍一下
    2025-12-12
  • 在C#中将Word转换为PostScript的代码实现

    在C#中将Word转换为PostScript的代码实现

    在需要高质量打印或跨平台文档分发的场景中,将Word转换为PostScript是专业选择,所以本文给大家介绍了如何在 C# 中将 Word 转换为 PostScript,需要的朋友可以参考下
    2025-09-09
  • C# 检索不区分大小写并高亮显示实例详解

    C# 检索不区分大小写并高亮显示实例详解

    这篇文章主要介绍了C# 检索不区分大小写并高亮显示实例详解的相关资料,需要的朋友可以参考下
    2017-01-01
  • C#灰度化图像的实例代码

    C#灰度化图像的实例代码

    灰度化一幅图像就是将图像的色彩信息全部丢掉,将24位的位图信息,用8位来表示,灰度图共有256级灰度等级,也就是将24位位图的一点如(255,255,255)转换成255,所以R,G,B三个值所乘的系数和为1
    2013-09-09
  • C#/VB.NET实现HTML转为XML的示例代码

    C#/VB.NET实现HTML转为XML的示例代码

    可扩展标记语言(XML)文件是一种标准的文本文件,它使用特定的标记来描述文档的结构以及其他特性。本文将利用C#实现HTML转为XML,需要的可以参考一下
    2022-06-06
  • C#实现鼠标消息捕获

    C#实现鼠标消息捕获

    这篇文章介绍了C#实现鼠标消息捕获的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • C#获取不重复的编码的最佳实践

    C#获取不重复的编码的最佳实践

    本文针对软件开发中“为新对象分配唯一编码”的常见需求,以C#通信设备管理场景为例,从原始代码分析入手,逐步讲解基于LINQ和哈希集合的优化方案,帮助开发者理解不同场景下的最佳实践,需要的朋友可以参考下
    2025-09-09
  • C#实现窗体抖动的两种方法

    C#实现窗体抖动的两种方法

    这篇文章主要为大家详细介绍了C#实现窗体抖动的两种方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • C#迭代器方法介绍

    C#迭代器方法介绍

    这篇文章主要介绍了C#迭代器方法,可以使用foreach循环语句进行的迭代的方法,称为可迭代方法,或者迭代器方法,方法操作,想了解更多内容得小伙伴可以学习下面文章内容,希望给你的学习带来帮助
    2022-03-03
  • C# 运算符 ?、??、?: 各种问号的用法和说明

    C# 运算符 ?、??、?: 各种问号的用法和说明

    本文介绍C#中三种常见的问号运算符的使用方法,简单讲解给大家,希望对大家有所帮助。
    2016-04-04

最新评论