精易论坛

标题: 易转C# - 6 - 基本多线程 [打印本页]

作者: 陽陽陽    时间: 2023-7-15 00:24
标题: 易转C# - 6 - 基本多线程
备注都在源码里拉,写了好几天的,比网上那些大长串好多了。

[C#] 纯文本查看 复制代码

using System;
using System.Threading;

using System.Diagnostics;
using System.Runtime.InteropServices;


namespace ThreadExample
{
    class Program
    {

        static void Main(string[] args)
        {
            ZombieThreadExample();
            while (true)
            {
                Thread.Sleep(2000);
            }
        }
        //=============
        public static void ThreadPoolExample()
        {
            int Number, completionPortThreads;
            ThreadPool.GetMaxThreads(out Number, out completionPortThreads);
            ThreadPool.SetMaxThreads(100, completionPortThreads); //第二个参数一般不需要改变,ChatGPT解释是:
                                                                  //第二个参数completionPortThreads指定了完成端口线程的数量。
                                                                  //完成端口线程用于处理异步I/O操作的完成事件。
                                                                  //当一个I/O操作完成时,由完成端口线程池中的线程来调用相关的回调方法。
            ThreadPool.GetMinThreads(out Number, out completionPortThreads);
            ThreadPool.SetMinThreads(50, completionPortThreads);


            for (int i = 0; i < 500; i++)
            {
                ThreadPool.QueueUserWorkItem(ThreadPoolThread, i);

                //new WaitCallback(ThreadPoolThread) //也可以
            }

            Console.ReadLine();
        }
        public static void ThreadPoolThread(object state)
        {
            Console.WriteLine("Task {0} is running on a thread from the thread pool.", state);
            Thread.Sleep(1000);
            Console.WriteLine("Task {0} exited.", state);
        }

        //=============
        public static void SpinLockExample()
        {
            // 互斥 、自旋、非重入、只能用于极短暂的运算。
            //会一直占用CPU
            //New Bing答案:
            SpinLock _spinLock = new SpinLock();
            bool lockTaken = false;
            try
            {
                _spinLock.Enter(ref lockTaken);
                // Do some work here.
            }
            finally
            {
                if (lockTaken) _spinLock.Exit();
            }
        }
        //=============
        public static volatile testClass testc = new testClass();
        public static volatile int a = 0;
        public static void Interlocked_volatileExample()
        {

            // volatile ≠ 数据不丢失
            //由于中断只能在当前指令完成后提供服务,因此即使内存未对齐,数据也永远不会损坏。

            // https://stackoverflow.com/questi ... eyword-be-used-in-c

            //经过测试:class
            //volatile - 49871
            //no volatile - 49843


            // a
            //原子锁 ----- volatile ------ 值1 ------- 值2
            // √   -----  √    -----    50000 -----  50000
            // √   -----  ×    -----    50000 -----  50000
            // ×   -----  √    -----    49646 -----  49715
            // ×   -----  ×    -----    49764 -----  49350
            // volatile 关键字只能应用于 class 或 struct 的字段。 不能将局部变量声明为 volatile。
            // 因为它们不在线程之间共享,但是a可以,编译器不报错


            Thread thread;

            for (int i = 0; i < 100; i++) // 100*500 = 50,000
            {
                thread = new Thread(() =>
                {

                    for (int i2 = 0; i2 < 500; i2++)
                    {
                        Interlocked.Increment(ref a);
                        testc.a++;
                        //Interlocked.Increment(ref testc.a);
                        Thread.Sleep(10);
                    }


                });
                thread.Start();
            }


            Thread.Sleep(10000);
            Console.WriteLine($"a:{a}");
            Console.WriteLine($"testc.a:{testc.a}");
        }
        //=============
        public static void JoinExample()
        {
            Stopwatch stopwatch = new Stopwatch();
            Thread thread = new Thread(() =>
            {
                Thread.Sleep(100000);
            });
            Thread thread1 = new Thread(() =>
            {
                Console.WriteLine("starting");
                thread.Join(2000); //等待线程1,超时2000秒
                Console.WriteLine("finished");

            });

            stopwatch.Start();


            thread.Start();
            thread1.Start();
            thread1.Join();


            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds); // Thread.Sleep(100000);
        }

        //=============
        public static Mutex mutex = new Mutex(false, "Global\\MyApp_TestApp_gfh5e3rsfdiuhvw9rttbfwhb43 "); //加上Global关键字无视切换user
        //禁止程序重复运行
        //互斥体
        public static void mutexExample()
        {
            Console.WriteLine(Process.GetCurrentProcess().MainModule.FileName);

            if (!mutex.WaitOne(1000))
            {
                mutex.Dispose();
                Console.WriteLine("Can not enter!");
                Console.ReadLine();
                Environment.Exit(1);
            }

            //mutex.ReleaseMutex();


            AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) =>
            {
                //Process.Start("calc.exe");
                //Process.Start(Process.GetCurrentProcess().MainModule.FileName); //作死行为
                mutex.Dispose();

            };

            while (true)
            {
                Console.WriteLine("enter...");
                Thread.Sleep(2000);
            }
        }

        //=============
        public static void AutoResetEvent() //单个释放线程
        {
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);

            Thread thread;
            Random random = new Random();
            Console.WriteLine("creating");
            for (int i = 0; i < 5; i++)
            {
                thread = new Thread(() =>
                {
                    autoResetEvent.WaitOne();
                    Console.WriteLine("Start to working");
                    //autoResetEvent.Reset(); //不需要
                    Thread.Sleep(1000);
                    Console.WriteLine($"exit");
                    autoResetEvent.Set();


                });
                thread.Start();
            }
            Console.WriteLine("created");
            autoResetEvent.Set();
        }
        public static void AutoResetEvent_ResetExample()
        {
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);

            Thread thread;


            Console.WriteLine("creating");
            thread = new Thread(() =>
            {
                autoResetEvent.WaitOne();
                Console.WriteLine("Start to working");
                Thread.Sleep(1000);
                Console.WriteLine($"exit");
            });

            autoResetEvent.Reset(); //如果被reset,会阻止执行WaitOne
            thread.Start();

            Thread.Sleep(4000);
            Console.WriteLine("set");
            autoResetEvent.Set();



        }
        //=============
        public static void ManualResetEvent() //会释放阻塞的所有线程
        {
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);

            Thread thread;
            Random random = new Random();
            Console.WriteLine("creating");
            for (int i = 0; i < 5; i++)
            {
                thread = new Thread(() =>
                {
                    manualResetEvent.WaitOne();
                    Console.WriteLine("Start to working");
                    //manualResetEvent.Reset();
                    Thread.Sleep(1000);
                    Console.WriteLine($"exit");
                    //manualResetEvent.Set();


                });
                thread.Start();
            }
            Console.WriteLine("created");

            Thread.Sleep(2000);
            manualResetEvent.Set();

            manualResetEvent.Reset(); //reset之后会阻止waitone
            //如果没有reset,会继续执行waitone

            thread = new Thread(() =>
            {
                Console.WriteLine("last");
                manualResetEvent.WaitOne();
                Console.WriteLine("last Start to working");
                //manualResetEvent.Reset();
                Thread.Sleep(1000);
                Console.WriteLine($"exit");
                //manualResetEvent.Set();


            });

            thread.Start();


        }
        //=============
        public static void Semaphore() //信号量
        {
            Semaphore semaphore = new Semaphore(0, 5);
            Thread thread;
            Random random = new Random();
            Console.WriteLine("creating");
            for (int i = 0; i < 30; i++)
            {
                thread = new Thread(() =>
                {

                    semaphore.WaitOne();
                    Console.WriteLine("Star to sleep");
                    //Thread.Sleep(5000);
                    Thread.Sleep(random.Next(1000, 3001));
                    Console.WriteLine($"avalible number {semaphore.Release()}");


                });
                thread.Start();
            }
            Console.WriteLine("created");
            for (int i = 0; i < 5; i++)
            {
                semaphore.Release();
            }
        }
        //=============
        public static void MonitorExample()
        {
            //lock关键字是基于monitor的

            object monitor = new object();
            Thread thread;
            for (int i = 0; i < 50; i++)
            {
                thread = new Thread(() =>
                {
                    if (!Monitor.TryEnter(monitor))
                    {
                        Console.WriteLine($"can not enter, waiting:{Thread.CurrentThread.ManagedThreadId}");
                        Monitor.Enter(monitor);
                    } //坑》》》》》TryEnter - 如果能进入,就进入,如果不能进入,就返回假并继续向下执行
                    Console.WriteLine("locking...");
                    Thread.Sleep(20);
                    Console.WriteLine("exit");
                    Monitor.Exit(monitor);
                });
                thread.Start();
            }
        }
        //=============
        [DllImport("kernel32.dll")]
        private static extern void ExitThread(uint dwExitCode);
        public static void ZombieThreadExample()
        {
            // https://stackoverflow.com/questi ... ombies-exist-in-net
            using (var file = System.IO.File.Open("test.txt", System.IO.FileMode.OpenOrCreate))
            {
                ExitThread(0);
            }
        }
        //=============

    }

    class testClass
    {
        public int a = 0;
    }
}




ps:volatile class没搞明白,有谁懂吗,谢谢谢谢

作者: 陽陽陽    时间: 2023-7-15 00:26
说真的,自己不敢相信这是自己写出来的
作者: E语言|菜鸟    时间: 2023-7-15 00:28
c#不好使啊。。写的一下给人拿走了
作者: 陽陽陽    时间: 2023-7-15 00:38
E语言|菜鸟 发表于 2023-7-15 00:28
c#不好使啊。。写的一下给人拿走了


反汇编固然厉害,但当我全部开源,阁下又将如何应对
作者: Canada    时间: 2023-7-15 10:25
c#应该也有输入api名字,自动声明的插件吧
作者: 江畔孤舟    时间: 2023-7-27 20:52
Task好用些吧?
作者: 陽陽陽    时间: 2023-7-28 00:14
江畔孤舟 发表于 2023-7-27 20:52
Task好用些吧?

大佬,我还没有学到
作者: 江畔孤舟    时间: 2023-7-29 09:56
陽陽陽 发表于 2023-7-28 00:14
大佬,我还没有学到

我也是刚学.都还不懂,委托啊,还有async/await也都很难搞懂
作者: 陽陽陽    时间: 2023-8-2 01:34
补充一些小知识:
                        Interlocked.Increment(ref a); //加一
                        Interlocked.Add(ref a, -10);  //减10
                        Interlocked.Exchange(ref a, 99); //赋值

                        //例如,要原子地将一个整数变量的值设置为10,但仅当它当前的值为7时,可以这样写:
                        Interlocked.CompareExchange(ref a, 10, 7);
                        //Interlocked.CompareExchange(ref int location1, int value, int comparand)

作者: qc999    时间: 2025-6-10 23:07
学习了。。。。。
作者: xf702    时间: 2025-6-28 14:57
屎山又何妨,只要能运行。。




欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4