c# 线程的等待(堵塞)

这里我要强调一个概念,

多线程是多线程,

异步编程是异步编程

这两个是有区别的概念;

我可以说多线程天生就要异步的特点;但你不能说多线程成就等同于我们的异步编程;

根不能说异步编程就是我们的多线程。这里不要搞混淆了;

再net中的进化如下:

多线程:Thread =>ThreadPool=> Task

异步编程:BenginInvokeXXX EndInvokeXXX IAsyncResult=> async await (这里面配合着Task的使用)。

好接下来,再来总结我们的线程(任务)的等待。

总结:

方法一:Thread.Sleep(),这个要预估,等待的时间应该大于我们的子线程执行的时间。

方法二:当然就是我们最常用的Join() 方法了,堵塞当前调用子线程成的方法,直到我们的子线程执行完毕。

方法二:主线程轮训子线程(这个是基于我们的IasyncResult 编程模式的,及时传说中的beginxxxx  endxxxx这种模式)

方法三:采用通知的方法就是我们的EevntWaitHanld = new AutoRestEevnt(false),然后waitOne 和 Set 的方式来进行的,效果非常好滴呀;

方法四:我把它命名为偏方:就是利用独占锁的机制,当子线程用完锁之后,释放,让给我们的主线程,前提是要确保我们的子线程先得到锁;

方法五:这个就是基于我们的Task的wait方法;

这里我给出一些,练习的demo,仅供参考使用;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication13
{
    //我们把它叫做等待子线程,或者,等待子线程一定的时间;
    //最原始的是使用 waitEevnt的方法;我们甚至可以用 poll的方式;
    //还有基于事件编程的回调方式;

    public class Person
    {

    }
    class Program
    {
        //evnet wait handle
        //该方法也可以用来进行线程的同步滴呀;
        public static object locker = new object();
        public static EventWaitHandle handler = new AutoResetEvent(false);

        public static void Eat()
        {
            Thread.Sleep(3000);
        }

        public static void Eat_WithSet()
        {
            Thread.Sleep(3000);

            handler.Set(); //子线程发出做完实行的信号;
        }

        public static void Eat_WithLock()
        {
            Console.WriteLine("枷锁开始");
            lock (locker)
            {
                Thread.Sleep(3000);   //假设,我们这里有很多的是事情要做的呀;
                //效果非常好;
            }
            Console.WriteLine("枷锁释放");
        }

        public static void Eat_Loop()
        {

            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                Console.WriteLine("子");
            }

        }

        //那么这个方法就不能为空了

        public static  void Eat_Wait()
        {
            for (int i = 0; i < 10; i++)
            {
                Task.Delay(1000).Wait();
                Console.WriteLine("子");
            }

        }

        public static void TestJoin()
        {

            Console.WriteLine("main start");

            Thread thread = new Thread(Eat);
            thread.Start();
            //给我等着;
            Console.WriteLine("主线程先做点其他事情;");
            //这我们我们可以直接用线程自带的方法;
            thread.Join();
            Console.WriteLine("好了,子线程事情做完了..");
            Console.WriteLine("main end");
            Console.ReadLine();

        }

        public static void Test_Set()
        {

            Console.WriteLine("main start");

            Thread thread = new Thread(Eat_WithSet);
            thread.Start();
            //给我等着;
            Console.WriteLine("主线程先做点其他事情;");
            handler.WaitOne();
            Console.WriteLine("好了,子线程事情做完了..");
            Console.WriteLine("main end");
            Console.ReadLine();

        }

        public static void Test11()
        {

            Console.WriteLine("main start");

            Thread thread = new Thread(Eat_WithSet);
            thread.Start();
            //给我等着;
            Console.WriteLine("主线程先做点其他事情;");
            handler.WaitOne(TimeSpan.FromSeconds(3));

            //注意这里,一点 waitone 和 task.wait 如果都指定了 等待的时间;
            //如果子线程在指定的时间内没有做完时间,那么我们就开始了主线程的方法;
            //这里并没有真正的取消线程;
            //问题又来了,如果去取消子线程呢;这个......

            Console.WriteLine("好了,不堵塞,主线程了,");
            Console.WriteLine("main end");
            Console.ReadLine();

        }
        //偏方
        public static void Test_Lock()
        {

            Console.WriteLine("main start");
            Thread thread = new Thread(Eat_WithLock);
            thread.Start();
            //给我等着;
            Console.WriteLine("主线程先做点其他事情;");

            //如果是单线层的话,我还是使用一点偏方;
            //那就是我们的lock方法滴呀;
            Thread.Sleep(20);//为了让子线程得到锁,我们这里估计sleep一下了
            //所以尼玛的叫偏方了;
            lock (locker)
            {
                //当然这种方式,就是完全出去一种四等的状态;
                //等待另外一个线程释放锁;
                Console.WriteLine("这个表示我们的另外一个线程执行完毕了;");
            }
            Console.ReadLine();

        }

        //如果要取消原来的方法的话,还得到原来的的方法去操作,整的是麻烦的一件事情;
        //不过有我们的Task 就方便多;;

        public static void Test_Task()
        {
            //task的取消就相对简单的多了;
            Console.WriteLine("main start");
            Task task = Task.Run(()=>Eat_Wait());

            Console.WriteLine("mian do something.then wait task");

           // task.Wait();  //默认情况下,它会等待task执行完毕;

            task.Wait(TimeSpan.FromSeconds(3));//在这里只能等待三秒,三秒只有,就不堵塞我们的主线程;
            //这里这的注意的事情是,等待不等于取消哦;
            //这一点是相对非常关键的啦;

            //先一节我们再来略略线程的取消啦滴呀;

            Console.WriteLine("task completed...");

            Console.WriteLine("main end");

            Console.ReadLine();

        }

        static void Main(string[] args)
        {

            //Test();
            //Test1();
            //Test11();
            //Test_Lock();
            //Test_Task();

        }
    }
}

//这里我再来演示一个set 之后,通知多个线程的实例,或则理解成为广播是似的传递消息;

或则:多个线程在等待某一个线程的信号;

时间: 2024-10-20 10:02:32

c# 线程的等待(堵塞)的相关文章

跟我学Java多线程——线程池与堵塞队列

前言 上一篇文章中我们将ThreadPoolExecutor进行了深入的学习和介绍,实际上我们在项目中应用的时候非常少有直接应用ThreadPoolExecutor来创建线程池的.在jdk的api中有这么一句话"可是,强烈建议程序猿使用较为方便的 Executors 工厂方法Executors.newCachedThreadPool()(无界线程池,能够进行自己主动线程回收).Executors.newFixedThreadPool(int)(固定大小线程池)和Executors.newSing

Java 并发编程中的 CyclicBarrier 用于一组线程互相等待

Java 5 引入的 Concurrent 并发库软件包中的 CyclicBarrier 是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用.因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier.CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在

CoreJava_线程并发(堵塞队列):在某个目录下搜索含有某keyword的文件

Java多线程编程是很考验一个程序猿水平的. 传统的WEB程序中.由于框架提供了太多的健壮性.并发性.可靠性的支持,所以我们都是将全部的注意力放到了业务实现上.我们不过依照业务逻辑的要求.不停的积累自己的代码. 由于知识,或者是经验的限制.常常出现了问题而不自知. 比如,某些比較原始的项目中.并没有使用Spring等相对来说比較灵活健壮的框架. 而是只使用Servlet来作为服务端的实现方式. 举一个简单的栗子.众所周知,当请求到了容器,容器是创建而且启动了一个Servlet线程来对当前的请求作

java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)

一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.concurrent.locks.ReentrantLock 锁,JDK也为我们提供了与此功能相应的类java.util.concurrent.locks.Condition.Condition与重入锁是通过lock.newCondition()方法产生一个与当前重入锁绑定的Condtion实例,我们

线程同步——内核对象实现线程同步——等待函数

1 对于内核对象实现线程同步,不得不提三点: 2 1)大多数内核对象既有触发也有未触发两个状态 3 比如:进程.线程.作业.文件流.事件.可等待的计时器.信号量.互斥量 4 2)等待函数:等待函数使线程自愿进入等待状态,直到指定的内核对象变为触发状态为止, 5 说道等待我们最喜欢不过了,因为这样不会浪费我们宝贵的CPU时间. 6 3)对于自动重置对象来说,当对象被触发时,函数会自动检测到(手动重置对象为触发是,函数也能检测到), 7 并开始执行,但是在函数会在返回之前使事件变为非触发状态. 8

线程系列09,线程的等待、通知,以及手动控制线程数量

当一个线程直到收到另一个线程的通知才执行相关的动作,这时候,就可以考虑使用"事件等待句柄(Event Wait Handles)".使用"事件等待句柄"主要用到3个类: AutoResetEvent, ManualResetEvent以及CountdownEvent(.NET 4.0以后才有).本篇包括: ※ 一个线程等待另一个线程的通知※ 2个线程互相通知等待※ 一个线程等待队列中的多个任务通知※ 手动控制线程的数量 □ 一个线程等待另一个线程的通知 最简单的情景

Android-Java多线程通讯(生产者 消费者)&amp;10条线程对-等待唤醒/机制的管理

上一篇博客 Android-Java多线程通讯(生产者 消费者)&等待唤醒机制 是两条线程(Thread-0 / Thread-1) 在被CPU随机切换执行: 而今天这篇博客是,在上一篇博客Android-Java多线程通讯(生产者 消费者)&等待唤醒机制 的基础上,扩大规模增加10条线程去执行 生产者 消费者: 注意:?? 上一篇博客是两条线程在执行(生产者 消费者)例如:当Thread-0 锁.wait(); 等待 冻结后,  Thread-1 锁.notify(); 唤醒的一定是 T

“全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第三十五章:如何获取线程被等待的时间? 下一章 "全栈2019"Java多线程第三十六章:如何设置线程的等待截止时间 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复&qu

dubbo连接zookeeper注册中心因为断网导致线程无限等待问题

最近维护的系统切换了网络环境,由联通换成了电信网络,因为某些过滤规则导致系统连不上zookeeper服务器(应用系统机器在深圳,网络为电信线路,zookeeper服务器在北京,网络为联通线路),因为我不是运维人员也不懂运维相关的技术,所以排查了很久也不知道原因,最后无奈之下把深圳这边的网络切回了联通,系统恢复正常. 但是因为本次事故体现了一个很严重的问题,即当zookeeper注册中心连不上时dubbo的线程会无限等待,因为系统有一些定时任务会比较频繁地开启新线程连接dubbo,所以导致的结果是