前言

众所周知,Thread类中的挂起线程和恢复线程微软已标记过时,因为可能会造成问题

  Resume()   恢复当前线程

已过时。 Resumes a thread that has been suspended.

  Suspend()   挂起当前线程

已过时。 挂起线程,或者如果线程已挂起,则不起作用。

其他方式实现

一、ThreadWorkItem

  class ThreadWorkItem
{
public int ThreadManagerId { get; set; }
public Thread Thread { get; set; }
public string ThreadName { get; set; }
public bool Flag { get; set; }
public ManualResetEvent ManualResetEvent { get; set; } }

二、C# Thread挂起线程和恢复线程的实现的两种方式

方式1:使用变量开关控制挂起线程和恢复线程,具体代码如下

    public class Program
{
//线程工作集合
private static List<ThreadWorkItem> Works = new List<ThreadWorkItem>(); //方式1:使用变量开关控制挂起线程和恢复线程 private static void Main(string[] args)
{
ThreadWorkItem wItem = null;
Thread t = null; var threadNum = ; for (int i = ; i < threadNum; i++)
{ t = new Thread(o=>
{
var w = o as ThreadWorkItem;
if (w == null) return;
while (true)
{
if (!w.Flag)
{
Console.WriteLine("我是线程:" + Thread.CurrentThread.Name);
Thread.Sleep();
continue;
}
//避免CPU空转
Thread.Sleep(); } });
//$ C#6.0语法糖
t.Name = $"Hello I'am 线程:{i}-{t.ManagedThreadId}";
wItem = new ThreadWorkItem
{
Flag = false,
Thread = t,
ThreadManagerId = t.ManagedThreadId,
ThreadName = t.Name
};
Works.Add(wItem);
t.Start(Works[i]);
} //5秒后允许一个等待的线程继续。当前允许的是线程1
Thread.Sleep();
Works[].Flag = true;
Console.WriteLine($"thread-{Works[0].ThreadName} is 暂停"); //5秒后允许一个等待的线程继续。当前允许的是线程0,1
Thread.Sleep();
Works[].Flag = false;
Console.WriteLine($"thread-{Works[0].ThreadName} is 恢复"); }
}

方式2:使用ManualResetEvent控制挂起线程和恢复线程(推荐);替代Thread类中被微软标记过时的函数(内核模式非混合模式)

    public class Program
{
//线程工作集合
static List<ThreadWorkItem> Works = new List<ThreadWorkItem>(); //方式2:使用ManualResetEvent控制挂起线程和恢复线程(推荐);替代Thread类中被微软标记过时的函数
static void Main(string[] args)
{ Task.Factory.StartNew(() =>
{
Thread t = null;
ThreadWorkItem item = null;
for (int i = ; i < ; i++)
{
t = new Thread((o) =>
{
var w = o as ThreadWorkItem;
if (w == null) return; while (true)
{
//阻塞当前线程
w.ManualResetEvent.WaitOne(); Console.WriteLine("我是线程:" + Thread.CurrentThread.Name);
Thread.Sleep();
} });
t.Name = "Hello,i 'am Thread: " + i;
item = new ThreadWorkItem
{
//线程0,1持续运行,设置true后非阻塞,持续运行。需要手动触发Reset()才会阻塞实例所在当前线程
ManualResetEvent = new ManualResetEvent(true),
Thread = t,
ThreadManagerId = t.ManagedThreadId,
ThreadName = t.Name
};
Works.Add(item);
t.Start(item);
} //5秒后准备暂停一个线程1。线程0持续运行 Thread.Sleep();
Console.WriteLine("close...");
Works[].ManualResetEvent.Reset(); //5秒后恢复线程1;线程0,1持续运行
Thread.Sleep();
Console.WriteLine("open...");
Works[].ManualResetEvent.Set(); //5秒后准备暂停一个线程0。线程1持续运行
Thread.Sleep();
Console.WriteLine("close0...");
Works[].ManualResetEvent.Reset(); //5秒后恢复线程1;线程0,1持续运行
Thread.Sleep();
Console.WriteLine("open0...");
Works[].ManualResetEvent.Set(); }); Console.ReadLine();
} }

三、总结

1.有时候会觉得必须由主线程创建ManualResetEvent实例才能起到作用,实际并不是这样的,上述方式2则证明了这一点。

2.那么AutoResetEvent做不到同样的效果吗?

答:AutoResetEvent 顾名思义,自动Reset()表示重置信号量状态,当前线程中持有WaitOne()就又会被持续阻塞。而ManualResetEvent必须要手动调用Reset()才能重置信号量,这里再解释下Set(),它表明允许一个或多个被同一个ManualResetEvent实例WaitOne()的线程放行。

3.实例化信号量的构造参数是什么意思?

答:信号量非终止状态,如果值为false则表明终止状态,调用WaitOne()方法的时候立即阻塞。设置true可以理解为隐式调用了Set()方法放行一次。

4. ManualResetEvent和AutoResetEvent的区别

     答:ManualResetEvent调用Set()允许一个或多个被同一个ManualResetEvent实例WaitOne()的线程放行。

           AutoResetEvent调用Set() 只能允许一个线程放行。如果多处使用同一个实例,则需要手动调用多次Set()

C# Thread挂起线程和恢复线程的更多相关文章

  1. MFC中挂起线程和恢复线程

    DWORD SuspendThread ( HANDLE hThread );   //挂起线程DWORD ResumeThread ( HANDLE hThread );   //恢复线程 比如说我 ...

  2. Java并发之线程管理(线程基础知识)

    因为书中涵盖的知识点比较全,所以就以书中的目录来学习和记录.当然,学习书中知识的时候自己的思考和实践是最重要的.说到线程,脑子里大概知道是个什么东西,但很多东西都还是懵懵懂懂,这是最可怕的.所以想着细 ...

  3. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  4. java线程技术6_线程的挂起和唤醒[转]

    转自:http://blog.chinaunix.net/uid-122937-id-215913.html 1. 线程的挂起和唤醒      挂起实际上是让线程进入“非可执行”状态下,在这个状态下C ...

  5. 使用 suspend 和 resume 暂停和恢复线程

    suspend 和 resume 的使用 在 Thread 类中有这样两个方法:suspend 和 resume,这两个方法是成对出现的. suspend() 方法的作用是将一个线程挂起(暂停), r ...

  6. java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍

       线程的概述:         线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...

  7. Java Thread.interrupt 害人! 中断JAVA线程(zz)

    http://www.blogjava.net/jinfeng_wang/archive/2012/04/22/196477.html#376322 ————————————————————————— ...

  8. 14.6.8 Configuring the InnoDB Master Thread IO Rate 配置InnoDB 主线程IO 速率:

    14.6.8 Configuring the InnoDB Master Thread IO Rate 配置InnoDB 主线程IO 速率: 主线程 在InnoDB 是一个线程 执行各种任务在后台. ...

  9. C# 显式创建线程 or 使用线程池线程--new Thread() or ThreadPool.QueueUserWorkItem()

    在C#多线程编程中,关于是使用自己创建的线程(Thread)还是使用线程池(ThreadPool)线程,一直很困惑,知道看了Jeffrey Richter的相关介绍才明白,记录如下: 当满足一下任何条 ...

随机推荐

  1. bzoj2200: [Usaco2011 Jan]道路和航线

    先忽略航线,求出图中所有连通块,再用航线拓扑排序求出每个连通块的优先级 然后dijkstra时优先处理优先级高的块里的点就行了 ps:这题SPFA会TLE #include <iostream& ...

  2. jQyery实现轮播器

    看到各大网站上都有一个轮播器的效果,自己不禁也想做一个,查了资料,看了轮播器的原理,慢慢的试着做了做,最终效果勉勉强强 原理:如图,试想一下,若是将<ul>的width属性值设置的很宽,直 ...

  3. 【BZOJ-2436】嘉年华 DP + 优化

    2436: [Noi2011]Noi嘉年华 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 529  Solved: 382[Submit][Statu ...

  4. codeforces 723F : st-Spanning Tree

    Description There are n cities and m two-way roads in Berland, each road connects two cities. It is ...

  5. SQL请求优化——请求次数统计,SQL写操作稀释

    引言 前几天做了这么一个东西:一个游戏中有个活动页面,活动页面有个商品,商品下面要显示该商品实浏览次数,就相当于是用户每出发一次请求这个浏览总次数都会添加一次,这个问题很简单,每次浏览的时候去数据库中 ...

  6. UVa 11998 Broken Keyboard (数组模拟链表问题)

    题目链接: 传送门 Broken Keyboard #include<bits/stdc++.h> using namespace std; char str[100010]; int m ...

  7. [转]如何启用Ubuntu的休眠模式

    大家都知道 Windows 有休眠模式,其实 Ubuntu 也有.休眠模式简单来说,就是可以在用户暂时离开时将内存中的所有内容都写入到硬盘当中,当用户下次开机时,就可以直接启动到上次保存的时间状态. ...

  8. plist文件的使用

    什么是plist文件 直接将数据写在代码里面,不是一种合理的做法.如果经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低 因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最 ...

  9. tableview的重用机制(面试必问)

    iphone重用机制是苹果为了实现大量数据显示而采用的一种节省内存的机制,比如在UITableView和ScrollView 等地方.为什么要“可重用”???对于我们的项目来说,内存控制是必不可少的, ...

  10. Exception:A generic error occurred in GDI+

    分析: 一般出现这种问题都是GDI和原数据(比如Bitmap)是同一个实体,只不过是两个引用.换句话说就是这个路径的图片被GDI占用啦. 还有一种情况是路径有问题. 场景一: WPF的Image控件的 ...