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

作者:袖梨 2022-06-25

C#多线程、跨线程与线程安全的示例详解(三种不同方法)

 代码如下 复制代码

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 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;
        }
    }

 
异步线程池

 代码如下 复制代码

delegate double weituo(double d);
        static weituo w = new weituo(perimeter);
        ///


        /// 计算周长
        ///

        ///
        public static double perimeter(double d)
        {
            return d * Math.PI;
        }
        ///
        /// 异步完成后回调的方法
        ///

        ///
        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();
        }

_________________________________
///


        /// 静态方法不需要实例化
        ///

        ///
        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();
        }

总结

优点:
·使用线程可以把占据长时间的程序中的任务放到后台去处理
·用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
·程序的运行速度可能加快
·在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

缺点:
·如果有大量的线程,会影响性能,因为操作系统需要在他们之间切换;
·更多的线程需要更多的内存空间
·线程会给程序带来更多的bug,因此要小心使用
·线程的中止需要考虑其对程序运行的影响
·通常块模型数据是在多个线程间共享的,需要一个合适的锁系统替换掉数据共享

相关文章

精彩推荐