C# 多线程、异步线程、线程池相关知识
/*
线程池ThreadPool类会在需要时增减池中线程的线程数,直到最大的线程数。池中的最大线程数是可配置的。
在双核CPU中,默认设置为1023个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,
以及线程池,中可用的最大线程数。如果有更多的作业要处理,线程池中线程的个数也到了极限,
最新的作业就要排队,且必须等待线程完成其任务。
*/ //下面这个方法是一个符合WaitCallBack委托的方法:
static void WaitCallBackMethod(object param)
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(String.Format("Thread {0} is running", param));
Thread.Sleep(1000);
}
}
//然后在主线程里给线程池添加方法,QueueUserWorkItem()方法的第二个参数是个object类型的参数,可传入一个数据到线程中 static void Main(string[] args)
{
for (int i = 1; i <= 3; i++)
{
ThreadPool.QueueUserWorkItem(WaitCallBackMethod, i);
}
Console.Read();
} /////////////////////////////////////////////////////////////////
//Task任务
1、Task类构造函数 使用Task类的构造函数。实例化Task对象时,任务不会立即运行,而是指定Created状态。
接着调用Task类的Start()方法来启动任务。
使用Task类时,除了调用Start()方法,还可以调用RunSynchronously()方法。
这样,任务也会启动,但是同时调用。默认情况下,任务是异步运行的。
Task类的构造函数接收一个无参无返回值的委托: Task task = new Task(TaskMethod);
task.Start(); 下面是TaskMethod方法:
static void TaskMethod()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(String.Format("Running in a task. Task ID: {0}", Task.CurrentId));
Thread.Sleep(500);
}
} 方法里用Task.CurrentId属性取得当前任务ID。下面是主线程:
static void Main(string[] args)
{
Task task = new Task(TaskMethod);
task.Start(); for (int i = 0; i < 10; i++)
{
Console.WriteLine("Running in main thread.");
Thread.Sleep(500);
} Console.Read();
} 如果要往线程里传递参数,Task构造函数提供的重载,可以传入一个object类型的参数:
Task task = new Task(TaskMethodWithParameter, "Hello world");
task.Start(); 下面是带参的线程方法:
static void TaskMethodWithParameter(object param)
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(String.Format("Running in a task. Parameter: {0}", param));
Thread.Sleep(500);
}
} 2、TaskFactory类
使用实例化的TaskFactory类,在其中把TaskMethod方法传递给StartNew()方法,就会立即启动任务。
TaskFactory tf = new TaskFactory();
tf.StartNew(TaskMethod); 3、Task.Factory属性
Task类提供了一个Factory静态属性,这个属性返回一个TaskFactory对象。
Task task = Task.Factory.StartNew(TaskMethod); ///////////////////////////////////////////////////////////////////////////////////
C#异步编程的实现方式——连续任务 通过任务,可以指定在任务完成后,应开始运行另一个特定任务。任务处理程序或者不带参数或者带一个对象参数,而连续处理程序有一个Task类型的参数。下面先定义两个任务: static void FirstTaskMethod()
{
Console.WriteLine(String.Format("Task {0} is doing something", Task.CurrentId));
Thread.Sleep(200);
} static void SecondTaskMethod(Task task)
{
Console.WriteLine("Last task is finished");
Console.WriteLine(String.Format("Task {0} is doing something", Task.CurrentId));
Thread.Sleep(200);
} 连续任务通过在任务上调用ContinueWith()方法来现实:
static void Main(string[] args)
{
Task task1 = new Task(FirstTaskMethod);
Task task2 = task1.ContinueWith(SecondTaskMethod);
task1.Start(); for (int i = 0; i < 20; i++)
{
Console.WriteLine("Main thread is running");
Thread.Sleep(200);
} Console.Read();
}
主线程循环输出字符串到控制台,Task1任务在另外一个线程里运行,FirstTaskMethod执行完继续SecondTaskMethod
值得注意的是,在一个任务结束时,可以启动多个任务,也就是说,任务的连接可以像一个树结构那样,如下代码: Task task1 = new Task(FirstTaskMethod);
Task task2 = task1.ContinueWith(SecondTaskMethod);
Task task3 = task1.ContinueWith(SecondTaskMethod);
Task task4 = task2.ContinueWith(SecondTaskMethod);
Task task5 = task2.ContinueWith(SecondTaskMethod);
无论前一个任务是如何结束的,后面的连续任务总是在前一个任务结束时启动。
TaskContinuationOptions枚举提供了OnlyOnFaulted,NotOnFaulted,OnlyOnCanceled,
NotOnCanceled,OnlyOnRunToCompletion几个选项。我们可以指定只有当前一个任务成功结束时才启动: Task task5 = task2.ContinueWith(SecondTaskMethod, TaskContinuationOptions.OnlyOnRanToCompletion); ///////////////////////////////////////////////////////////////////////////////////
C#异步编程的实现方式——层次任务 任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个层次结构。
下面的代码段在父任务内部新建一个任务。创建子任务的代码与创建父任务的代码相同,
唯一的区别是这个任务从另一个任务内部创建: static void Main(string[] args)
{
Task parentTask = new Task(ParentTask);
parentTask.Start(); Console.Read();
} static void ParentTask()
{
Console.WriteLine("Parent task is starting");
Task childTask= new Task(ChildTask,TaskCreationOptions.AttachedToParent);
childTask.Start();
Thread.Sleep(2000);
Console.WriteLine("Parent task is finished");
} static void ChildTask()
{
Console.WriteLine("Child task started");
Thread.Sleep(4000);
Console.WriteLine("Child task is finished");
} ///////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////// using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; namespace Ex.RulesTester.Threads
{
/// <summary>
/// Task异步等待所有线程结束通知测试
/// </summary>
[TestClass]
public class TaskAllCompleteTester
{
[TestMethod]
public void TestTaskPoolStatus()
{
//运行异步多任务
TaskTest.RunTask();
var list = TaskTest.SuccessList;
bool isAllComplete = false;
//等待异步通知
while (!isAllComplete)
{
isAllComplete = TaskTest.IsAllComplete;
list = TaskTest.SuccessList;
} Assert.IsTrue(true);
}
/// <summary>
/// 对于 task 多任务执行的封装
/// </summary>
private class TaskTest
{
private static object m_lock = new object();
public static List<string> SuccessList = new List<string>();
private static string msg = "";
public static bool IsFinish = false;
public static List<Task> TaskList = new List<Task>();
static bool isAllComplete = false;
/// <summary>
/// 标记所有任务是否全部执行完毕
/// </summary>
public static bool IsAllComplete
{
get { return isAllComplete; }
} private TaskTest()
{ } public static void RunTask()
{
//运行5个任务
for (int i = 1; i <= 5; i++)
{
var task = Task.Factory.StartNew(DoTask, i);
TaskList.Add(task);
}
//异步等待所有任务执行完毕
Task.Factory.StartNew(x =>
{
Task.WaitAll(TaskList.ToArray());
//标记所有任务运行完成
isAllComplete = true;
}, null);
}
private static void DoTask(object par)
{
Thread.Sleep(int.Parse(par.ToString()) * 1000);
lock (m_lock)
{
SuccessList.Add("Has Completed T" + par.ToString());
}
} }
}
}
C# 多线程、异步线程、线程池相关知识的更多相关文章
- c3p0 数据库连接池相关知识
c3p0数据库连接池的配置文件放在eclipse的src目录下,代码就可以识别. c3p0的配置文件的内容如下: <!-- Uncomment and set any of the option ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- 浅谈C#中的 async await 以及对线程相关知识的复习
C#5.0以后新增了一个语法糖,那就是异步方法async await,之前对线程,进程方面的知识有过较为深入的学习,大概知道这个概念,我的项目中实际用到C#异步编程的场景比较少,就算要用到一般也感觉T ...
- JDK 伪异步编程(线程池)
伪异步IO编程 BIO主要的问题在于每当有一个新的客户端请求接入时,服务端必须创建一个新的线程处理新接入的客户端链路,一个线程只能处理一个客户端连接.在高性能服务器应用领域,往往需要面向成千上万个客户 ...
- C#多线程(12):线程池
目录 线程池 ThreadPool 常用属性和方法 线程池说明和示例 线程池线程数 线程池线程数说明 不支持的线程池异步委托 任务取消功能 计时器 线程池 线程池全称为托管线程池,线程池受 .NET ...
- Java多线程--线程安全问题的相关研究
在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- 多线程二:线程池(ThreadPool)
在上一篇中我们讲解了多线程的一些基本概念,并举了一些例子,在本章中我们将会讲解线程池:ThreadPool. 在开始讲解ThreadPool之前,我们先用下面的例子来回顾一下以前讲过的Thread. ...
- GIL 线程/进程池 同步异步
GIL 什么是GIL 全局解释器锁,本质是一把互斥锁,是加在cpython解释器上的一把锁, 同一个进程内的所有线程需要先抢到GIL锁,才能执行python代码 为什么要有GIL cpython解释器 ...
随机推荐
- Go数组、切片、映射的原理--简明解析
数组.切片.映射是Golang的最重要的数据结构,下面是对这3种数据结构的一点个人总结: 一.数组 数组是切片和映射的基础数据结构. 数组是一个长度固定的数据类型,存储着一段具有相同数据类型元素的连续 ...
- Linux修改文件permission属性
列出文件属性 ls -al 修改文件属性为可读.可写 sudo chmod -c 777 <your file name>
- Mac环境下mysql初始化密码问题--If you lose this password, please consult the section How to Reset the Root Password in the MySQL reference manual.
个人在Mac上操作数据库,遇到的启动数据库问题的简单记录 1.苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭mysql服务(点击stop mysql server) 2.进 ...
- 团队作业8——Beta 阶段冲刺5th day
一.当天站立式会议 二.每个人的工作 (1)昨天已完成的工作(具体在表格中) 支付功能测试 (2)今天计划完成的工作(具体如下) 完善订单功能 (3)工作中遇到的困难(在表格中) 成员 昨天已完成的工 ...
- Swing-JList用法-入门
注:本文所有素材均来源于How to Use Lists,本文为该文章的学习笔记. JList是Swing中的列表控件,形状如下所示: 实际上,JList有3种不同的样式: 分别为HORIZONTAL ...
- 201521123064 《Java程序设计》第8周学习总结
1. 本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 集合内容见:<Java程序设计>第7周学习总结 1.2 选做:收集你认为有用的代码片段 ① Jav ...
- 201521123047 《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 答: - 只能有一个父类,即单继承,子类继承父类的全部成员(属性和方法),并可能有自己特有的 ...
- 201521123122 《java程序设计》第十二周学习总结
## 201521123122 <java程序设计>第十二周实验总结 ## 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将St ...
- linux segmentation fault记录
文章将记录linux学习使用中出现的各种segmentation fault,持续更新,希望对看到人有所帮助 1. linux pcap segmentation fault -- 2013.11.2 ...
- page分页类
<?php /** file: Page.class.php 完美分页类 Page */ class Page { private $total; //数据表中总记录数 private $lis ...