C#多线程、跨线程与线程安全的示例详解

8 篇文章 0 订阅
8 篇文章 0 订阅

http://www.111cn.net/net/160/52542.htm


1.委托,扩展方法,UI跨线程

using System.Threading;
public static class Extensions
    {
        //控件扩展方法(用于跨线程操作),因为为了线程的安全,防止资源竞争出现死锁或不一致的状态,.NET是不允许进行跨线程访问窗体控件的。
        public static void SafeCall(this Control ctrl, Action callback)
        {
            if (ctrl.InvokeRequired)
            {
                ctrl.Invoke(callback);
            }
            else
            {
                callback();
            }
        }

 //带返回值
        public static string SafeCall(this Control ctrl, Func<string> callback)
        {
            if (ctrl.InvokeRequired)
            {
                return (string )( ctrl.Invoke(callback) );//同步
            }
            else
            {
                return (string )( callback() );
            }
        }

    }
 
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;//方法二(禁用异常,不检查跨线程调用的安全问题,可以自由拖动窗体,不过在严格条件下也不可取,数据可能不一致)
 
            //方法三(推荐使用)
            //把你要保护起来的代码作为一个回调,然后任何需要保护一些代码的地方都可以这样调用
            ThreadPool.QueueUserWorkItem(h =>
            {
                int i = 0;
                while (true)
                {
                    //如果没有SafeCall方法,将出现“线程间操作无效: 从不是创建控件“textBox1”的线程访问它。”的错误
 
                    匿名委托
                    //textBox1.SafeCall(delegate()
                    //{
                    //    textBox1.Text = (i++).ToString();
                    //});
                    //Lambda表达式
                    textBox1.SafeCall(() =>
                    {
                        textBox1.Text = (i++).ToString();
                    });
                    //Thread.Sleep(100);
                }
            });
        }
 
        //抽奖示例
        public bool flag = true;
        public void choujiang()
        {
            flag = true;
            while (flag)
            {
                Random rnd = new Random();
                textBox1.Text = rnd.Next(1, 100).ToString();
                //Application.DoEvents();//方法一:这样也可以防止UI界面线程的阻塞,不至于被卡死。但是在拖动界面或其他操作的时候,程序会被暂停
            }
        }
        //开始
        private void button1_Click(object sender, EventArgs e)
        {
            //choujiang();//方法一
            new Action(choujiang).BeginInvoke(null, null);//方法二
        }
        //暂停
        private void button2_Click(object sender, EventArgs e)
        {
            flag = false;
        }
    }


2.异步委托

delegate double weituo(double d);
        static weituo w = new weituo(perimeter);
        /// <summary>
        /// 计算周长
        /// </summary>
        /// <param name="d"></param>
        public static double perimeter(double d)
        {
            return d * Math.PI;
        }
        /// <summary>
        /// 异步完成后回调的方法
        /// </summary>
        /// <param name="result"></param>
        public static void method(IAsyncResult result)
        {
            Console.Write("hi~");
            Console.WriteLine(w.EndInvoke(result));
        }

        static void Main(string[] args)
        {
            //开始异步执行
            w.BeginInvoke(10, new AsyncCallback(method), null);
            w.BeginInvoke(20, new AsyncCallback(method), null);
            Console.Read();
        }

3.线程池+委托
/// <summary>
        /// 静态方法不需要实例化
        /// </summary>
        /// <param name="d"></param>
        public static void perimeter(object d)
        {
            Console.WriteLine(Math.PI * (double)d);
            Thread.Sleep(1000);
        }
        static void Main(string[] args)
        {
            int i = 1;
            WaitCallback wcb = new WaitCallback(perimeter);
            while (i < 15)
            {
                //将任务排入队列以便执行,您的回调方法将在某个线程池线程可用时执行
                ThreadPool.QueueUserWorkItem(wcb, (double)i);
                ++i;
            }
            Console.Read();
        }

===========================================================================================================================================

在多线程的情况下为了整个程序退出调用 System.Environment.Exit(System.Environment.ExitCode);

thread.Abort()很多时候不管用,它只是建议线程结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值