C# 委托

猿掌柜
2021-12-15 / 0 评论 / 39 阅读 / 正在检测是否收录...

c#委托

{mtitle}winform{/mtitle}

delegate void SetTextCallback(double[] text);
SetTextCallback deg = new SetTextCallback(SetText);
this.Invoke(deg, new object[] { new double[] { Convert.ToDouble(cnt), val,max,min, change } });
private void SetText(double[] text)
        {
            label19.Text = text[0] + "";

            textBox6.Text = text[3] + "";
            textBox7.Text = text[2] + "";
            textBox3.Text = (1000/text[4]).ToString("f2");
            label26.Text = (text[2] - text[3]).ToString("f3");
        }

{mtitle}wpf{/mtitle}

App.Current.Dispatcher.BeginInvoke(new Action(() => {
                        Fpsnum.Content = fpsnum + "";
                    }));

{mtitle}高级用法{/mtitle}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace multiThread
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
            //指定不再捕获对错误线程的调用
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        #region 最基本的多线程调用
        private void btn_Update_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(DataUpdate));
            t.Start();
        }

        /// <summary>
        /// 数据处理
        /// </summary>
        private void DataUpdate()
        {
            //通过循环,模拟数据处理过程
            for (int i = 0; i < 10; i++)
            {
                //在未设置CheckForIllegalCrossThreadCalls情况下,如果直接操作memoEdit_main,则会弹出【线程间操作无效: 从不是创建控件XXX的线程访问它】错误
                memoEdit_main.Text = memoEdit_main.Text + "\r\n" + DateTime.Now.ToString();
                //MessageBox.Show(DateTime.Now.ToString());
                //暂停1s
                Thread.Sleep(1000);
            }
            MessageBox.Show("处理完成!");
        }
        #endregion

        #region 使用INVOKE方法通过子线程更新主线程控件
        /// <summary>
        /// 1、定义界面更新操作
        /// 更新Memoedit信息并定位到行尾
        /// </summary>
        /// <param name="strMsg"></param>
        private void MainThreadUIOper(string strMsg)
        {
            memoEdit_main.Text = memoEdit_main.Text + "\r\n" + strMsg;
            memoEdit_main.SelectionStart = memoEdit_main.Text.Length;
            memoEdit_main.ScrollToCaret();
            Application.DoEvents();
        }
        /// <summary>
        /// 2、定义委托事件,用于委托上一步定义的MainThreadUIOper
        /// </summary>
        /// <param name="str"></param>
        public delegate void UIOperDelegate(string str);
        /// <summary>
        /// 3、定义子线程执行操作函数
        /// </summary>
        /// <param name="strMsg"></param>
        private void DoWork(object para)
        {
            string strPara = para.ToString();
            for (int i = 0; i < 10; i++)
            {
                //注意BeginInvoke和Invoke的区别,根据实际情况选用,前者为异步,后者为同步
                //也可以将new UIOperDelegate(MainThreadUIOper)提出来单独定义  UIOperDelegate temp = new UIOperDelegate(MainThreadUIOper);  后面公共引用
                this.Invoke(new UIOperDelegate(MainThreadUIOper), new object[] { DateTime.Now.ToString() });
                //暂停1s
                Thread.Sleep(1000);
            }
            //完成后发送相关信息
            this.BeginInvoke(new UIOperDelegate(MainThreadUIOper), new Object[] { "测试完成!" });
            //使用 MessageBoxOptions.ServiceNotification是的窗口始终在最上一层显示
            MessageBox.Show("提示", "测试完成!", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification);
        }
        /// <summary>
        /// 4、在主线程中开启子线程并传递参数给子线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_start_Click(object sender, EventArgs e)
        {
            memoEdit_main.Text = "";
            memoEdit_main.Update();
            //注意,如果需要给子线程传递参数,需要使用ParameterizedThreadStart,否则使用ThreadStart即可,后面直接thread.Start();
            Thread thread = new Thread(new ParameterizedThreadStart(DoWork));
            thread.Start("para");
        }
        #endregion


        #region 使用BackgroundWorker方法进行异步操作
        /// <summary>
        /// 1、定义BackgroundWorker对象
        /// </summary>
        private BackgroundWorker m_backgroundWorker = null;
        /// <summary>
        /// 2、主体方法,定义子操作函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void m_backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                //在线程中更新UI(通过ReportProgress方法)
                m_backgroundWorker.ReportProgress(50, DateTime.Now.ToString());
                //暂停1s
                Thread.Sleep(1000);
            }
            //完成后发送相关信息
            m_backgroundWorker.ReportProgress(100, "操作完成");
        }
        /// <summary>
        /// 3、定义执行UI更新事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void m_backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            memoEdit_main.Text = memoEdit_main.Text + "\r\n" + e.UserState.ToString();
            memoEdit_main.SelectionStart = memoEdit_main.Text.Length;
            memoEdit_main.ScrollToCaret();
            Application.DoEvents();
        }
        /// <summary>
        /// 4、注册事件(执行线程主体、执行UI更新事件)
        /// 启动子线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_prop_Click(object sender, EventArgs e)
        {
            m_backgroundWorker = new System.ComponentModel.BackgroundWorker();
            //设置报告进度更新,注意此选项必须设置为true,否则无法返回进度
            m_backgroundWorker.WorkerReportsProgress = true;
            //注册线程主体方法
            m_backgroundWorker.DoWork += new DoWorkEventHandler(m_backgroundWorker_DoWork);
            //注册更新UI方法
            m_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(m_backgroundWorker_ProgressChanged);
            //注册子线程执行完成事件
            m_backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.m_backgroundWorker_RunWorkerCompleted);
            this.m_backgroundWorker.RunWorkerAsync();
        }
        /// <summary>
        /// 子线程执行完成后操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void m_backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("操作完成!");
        }
        #endregion

        #region 通过UI线程的SynchronizationContext的Post/Send方法更新UI
        /// <summary>
        /// 1、定义UI线程的同步上下文
        /// </summary>
        SynchronizationContext m_SyncContext = null;
        /// <summary>
        /// 3、定义线程的主体方法
        /// </summary>
        private void ThreadProcSafePost()
        {
            for (int i = 0; i < 10; i++)
            {
                //在线程中更新UI(通过UI线程同步上下文m_SyncContext)
                m_SyncContext.Post(SetTextSafePost, DateTime.Now.ToString());
                //暂停1s
                Thread.Sleep(1000);
            }
            //完成后发送相关信息
            m_SyncContext.Post(SetTextSafePost, "操作完成");
        }
        /// <summary>
        /// 4、更新UI方法
        /// </summary>
        /// <param name="text"></param>
        private void SetTextSafePost(object str)
        {
            memoEdit_main.Text = memoEdit_main.Text + "\r\n" + str.ToString();
            memoEdit_main.SelectionStart = memoEdit_main.Text.Length;
            memoEdit_main.ScrollToCaret();
            Application.DoEvents();
        }
        /// <summary>
        /// 2、获取UI线程同步上下文(建议在窗体构造函数或FormLoad事件中,这里因为测试方便,直接放在了这里)
        /// 启动线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_sync_Click(object sender, EventArgs e)
        {
            //获取UI线程同步上下文
            m_SyncContext = SynchronizationContext.Current;
            Thread thread = new Thread(new ThreadStart(this.ThreadProcSafePost));
            thread.Start();
        }
        #endregion
    }
}
1

评论 (0)

取消