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的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

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

    一.工具类代码 public class TaskHelper { #region 多线程操作 /// <summary> /// 功能描述:多线程执行方法,方法无参数,无返回值 /// </summary> /// <param name="func">方法,如果方法中调用了控件,请使用 ThreadInvokerControl(() => { 您的操作})进行包括</param> /// <param name="

  • C#之WinForm跨线程访问控件实例

    本文实例讲述了C#中WinForm跨线程访问控件的实现方法,分享给大家供大家参考. 具体实现方法如下: 1.跨线程访问控件委托和类的定义 复制代码 代码如下: using System; using System.Windows.Forms; namespace ahwildlife.Utils {     /// <summary>     /// 跨线程访问控件的委托     /// </summary>     public delegate void InvokeDeleg

  • C#中跨线程访问控件问题解决方案分享

    net 原则上禁止跨线程访问控件,因为这样可能造成错误的发生,推荐的解决方法是采用代理,用代理方法来间接操作不是同一线程创建的控件. 第二种方法是禁止编译器对跨线程访问作检查,可以实现访问,但是出不出错不敢保证Control.CheckForIllegalCrossThreadCalls = false; 最近我在做一个项目,遇到了跨线程要去访问页面控件.但是总是提示出错,不能在其它线程中修改创建控件的线程的控件的值,后来采用了匿名代理,结果很轻松地解决了.解决过程如下:首先在窗体上,创建一个l

  • C#实现跨线程操作控件方法

    本文实例讲述了C#实现跨线程操作控件方法,分享给大家供大家参考.具体实现方法如下: 由于在.net平台下Winform.wpf禁止跨线程直接访问控件,因此在必须跨线程访问控件的时候采用异步方式. 1.winform项目中跨线程访问控件: 编写一个Winform小实例:在做winform项目中,有时为了将系统运行的状态实时显示到Form中,因此添加一个RichTextbox控件实时显示系统运行日志.本例实现的操作是将日志以字符串的形式写入RichTextbox控件,因为是实时显示,所以涉及到跨线程

  • C# winform跨线程操作控件的实现

    前提:当我们使用Winform开发的时候,经常会遇到:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“xxxx”的线程访问它.” 原因:发生次异常的原因是因为winform在渲染UI界面和操作界面数据的时候使用的是同一个线程.当我们创建另外一个线程,去操作此线程的UI控件,会导致线程不安全.winform为了防止线程不安全,因此杜绝了这个跨线程操作,并且抛出异常. 异常举例:创建两个控件,一个是按钮控件,一个是lable控件 private

  • Winform中如何跨线程访问UI元素

    在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应, 同时我们又需要在工作线程中更新UI界面上的控件.但直接访问会出现"线程间操作无效"的情况,因为.NET禁止了跨线程调用控件, 否则谁都可以操作控件,最后可能造成错误. 下面介绍几种跨线程访问的方法: 1.禁止对跨线程访问做检查 (不推荐使用这种方法) 这种方法不检查跨线程访问,允许各个线程操作UI元素,容易出现错误. public Form2() { InitializeComponent(); //禁

  • C#多线程与跨线程访问界面控件的方法

    本文实例讲述了C#多线程与跨线程访问界面控件的方法.分享给大家供大家参考.具体分析如下: 在编写WinForm访问WebService时,常会遇到因为网络延迟造成界面卡死的现象.启用新线程去访问WebService是一个可行的方法. 典型的,有下面的启动新线程示例: 复制代码 代码如下: private void LoadRemoteAppVersion()  {      if (FileName.Text.Trim() == "") return;      StatusLabel

  • Java使用多线程异步执行批量更新操作方法

    写在前面: 相信不少开发者在遇到项目对数据进行批量操作的时候,都会有不少的烦恼,尤其是针对数据量极大的情况下,效率问题就直接提上了菜板.因此,开多线程来执行批量任务是十分重要的一种批量操作思路,其实这种思路实现起来也十分简单,就拿批量更新的操作举例: 整体流程图 步骤 获取需要进行批量更新的大集合A,对大集合进行拆分操作,分成N个小集合A-1 ~ A-N . 开启线程池,针对集合的大小进行调参,对小集合进行批量更新操作. 对流程进行控制,控制线程执行顺序. 按照指定大小拆分集合的工具类 impo

  • C# 委托(跨窗体操作控件)实例流程讲解

    效果描述:有两个窗体,FORM1(一个名为"打开form2"的button控件)和FORM2(一个名为"改变form1颜色"的button控件).启动时,FORM1中点击button控件"打开form2""使FORM2显示出来.点击FORM2中的"改变form1颜色"后,Form1中颜色改变. 一.在Form2里面:       首先声明一个委托和委托实例Form2类外 复制代码 代码如下: public deleg

  • Java创建多线程异步执行实现代码解析

    实现Runable接口 通过实现Runable接口中的run()方法 public class ThreadTest implements Runnable { public static void main(String[] args) { Thread thread = new Thread(new ThreadTest()); thread.start(); } @Override public void run() { System.out.println("Runable 方式创建的新

随机推荐