c#之多线程之为所欲为
一 什么是多线程
1、 什么是进程?一个 exe 运行一次就会产生一个进程,一个 exe 的多个进程之 间数据互相隔离。
2、 一个进程里至少有一个线程:主线程。我们平时写的控制台程序默认就是单线程的,代 码从上往下执行,一行执行完了再执行下一行;
3、 什么是多线程:一个人两件事情同时做效率高。同一时刻一 个人只能干一件事情,其实是在“快速频繁切换”,如果处理不当可能比不用多线程效率还低
二 Thread 对象
2.1 thread基础写法
public static void ThreadTest()
{
int a = 0;
Thread thread1 = new Thread(m=>
{
for (int i = 0; i < 20; i++)
{
a = a + 1;
Console.WriteLine("线程1:"+ a);
} }); Thread thread2 = new Thread(m =>
{
for (int i = 0; i < 20; i++)
{
a = a + 1;
Console.WriteLine("线程2:"+ a);
} }); thread1.Start();
thread2.Start();
Console.ReadKey();
}
这段代码输出结果如下:
可以看出两个子线程启动后是并行执行的,所以输出结果没有按照顺序来

2.2 设置线程的优先级
thread1.Priority=ThreadPriority。。。
2.3 t1.Join()当前线程等待 t1 线程执行结束,实例如下:
这段代码执行过后输出的结果就是正常的从1输出到了40
public static void ThreadTest()
{
int a = ;
Thread thread1 = new Thread(m=>
{
for (int i = ; i < ; i++)
{
a = a + ;
Console.WriteLine("线程1:"+ a);
} }); Thread thread2 = new Thread(m =>
{
//等待thread1线程任务完成后在执行
thread1.Join();
for (int i = ; i < ; i++)
{
a = a + ;
Console.WriteLine("线程2:"+ a);
} });
//可以将参数传入到子线程中
thread1.Start(a);
//thread1.Join(); 或者将Join放在这里
thread2.Start(a);
Console.ReadKey(); }
2.4 Interrupt方法
Interrupt 用于提前唤醒一个在 Sleep 的线程,Sleep 方法会抛出 ThreadInterruptedException 异常 代码如下:
代码输出到9的时候线程会休眠8秒钟,但是运行到主线程thread1.Interrupt()时,子线程会被唤醒,然后执行catch里面的Console.WriteLine("线程被唤醒");之后接着从10开始输出到2000。需要注意的是只有线程自身能让自身休眠
public static void ThreadTest2()
{
Thread thread1 = new Thread(() =>
{
for (int i = 0; i < 2000; i++)
{
if (i==10)
{
//唤醒线程之后会引发ThreadInterruptedException类型的异常,所以需要try catch
try
{
//子线程休眠8秒钟
Thread.Sleep(8000);
}
catch (ThreadInterruptedException ex)
{
Console.WriteLine("线程被唤醒");
}
}
Console.WriteLine(i);
}
});
thread1.Start();
//提前唤醒在沉睡的子线程
Thread.Sleep(3000);
thread1.Interrupt();
Console.ReadKey();
}
三 线程池
3.1、线程池:因为每次创建线程、销毁线程都比较消耗 cpu 资源,因此可以通过线程池进行 优化。线程池是一组已经创建好的线程,随用随取,用完了不是销毁线程,然后放到线程池 中,供其他人用。
3.2、用线程池之后就无法对线程进行精细化的控制了(线程启停、优先级控制等)
3.3、ThreadPool 类的一个重要方法:
static bool QueueUserWorkItem(WaitCallback callBack)
static bool QueueUserWorkItem(WaitCallback callBack, object state)
3.4、除非要对线程进行精细化的控制,否则建议使用线程池,因为又简单、性能调优又更好。
//QueueUserWorkItem是一个静态方法不需要New
public static void ThreadPool()
{
System.Threading.ThreadPool.QueueUserWorkItem(m=>
{
for (int i = 0; i < 1000; i++)
{
i++;
Console.WriteLine(i);
}
});
Console.ReadKey();
}
四 TPL风格的异步方法
TPL(Task Parallel Library)是.Net 4.0 之后带来的新特性,更简洁,更方便。现在在.Net 平台下已经大面积使用。
注意方法中如果有 await,则方法必须标记为 async,不是所有方法都可以被轻松的标记 为 async。WinForm 中的事件处理方法都可以标记为 async、MVC 中的 Action 方法也可以标 记为 async、控制台的 Main 方法不能标记为 async。 TPL 的特点是:方法都以 XXXAsync 结尾,返回值类型是泛型的 Task<T>。 TPL 让我们可以用线性的方式去编写异步程序,不再需要像 EAP 中那样搞一堆回调、逻 辑跳来跳去了。
/TPL风格返回的Task<T> 泛型的数据
//await 关键字等待异步方法返回
public static async void Task()
{
WebClient wc = new WebClient();
string s= await wc.DownloadStringTaskAsync("http://www.baidu.com");
Console.WriteLine(s);
Console.ReadKey();
}
public static void Task2()
{
WebClient wc = new WebClient();
//若果不使用await关键字就得使用Task<string>类型来接收数据
Task<string> s2 = wc.DownloadStringTaskAsync("http://www.baidu.com");
Console.ReadKey();
}
自己编写一个TPL风格的异步方法:
使用了async关键字就必须返回Task泛型数据类型的数据
public static Task<string> StringAsync()
{
return Task.Run(() =>
{
Thread.Sleep(5000);
return "hehe";
}); }
// GET: Home
public async Task<ViewResult> Index()
{ var s = await StringAsync();
return View();
}
如果返回值就是一个立即可以随手可得的值,那么就用 Task.FromResult() 如果是一个需要休息一会的任务(比如下载失败则过 5 秒钟后重试。主线程不休息,和 Thread.Sleep 不一样),那么就用 Task.Delay()。 3、Task.Factory.FromAsync()把 IAsyncResult 转换为 Task,这样 APM 风格的 api 也可以用 await 来调 用。 4、编写异步方法的简化写法。如果方法声明为 async,那么可以直接 return 具体的值,不再用创建 Task,由编译器创建 Task:
static async Task<int> F1Async()
{
return 1;
} static Task<int> F2Async()
{
return Task.FromResult(3);
} static Task<int> F3Async()
{
return Task.Run(()=> {
return 1 + 3; });
}
一定要让 async 的传染性(调用异步方法要用 await,用了 await 方法就要声明为 async,调 用我这个 async 方法的地方必须要 await……)不要轻易直接调用 Task 的 Wait、WaitAll 等方 法。等待一个用 await,而不是 task.Wait();等待多个用 await Task.WhenAll(),而不是 Task.WaitAll()
c#之多线程之为所欲为的更多相关文章
- Java并发编程:Java实现多线程的几种方式
在Java中,多线程主要的实现方式有四种:继承Thread类.实现Runnable接口.实现Callable接口通过FutureTask包装器来创建Thread线程.使用ExecutorService ...
- 「建议心心」要就来15道多线程面试题一次爽到底(1.1w字用心整理)
. 本文是给**「建议收藏」200MB大厂面试文档,整理总结2020年最强面试题库「CoreJava篇」**写的答案,所有相关文章已经收录在码云仓库:https://gitee.com/bingqil ...
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- Java多线程
一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程 ...
- .NET基础拾遗(5)多线程开发基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- Java多线程基础——对象及变量并发访问
在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
随机推荐
- iOS中 Animation 动画大全 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博! iOS开发者交流QQ群: 446310206 1.iOS中我们能看到的控件都是UIView的子类,比如UIButt ...
- TCP/IP入门(2) --网络层
/** 本篇博客由 126(127不可用) 2^24 -2 B 2^14 -1 128.1 191.255 2^16 -2 C 2^21 -1 192.0.1 223.255.255 2^8 -2 D ...
- linux下重启weblogic(关闭和启动)
ssh远程连接Linux服务器! 开启weblogic: 1.找到/Oracle/Middleware/user_projects/domains/用户_domain目录, 2.执行nohup ...
- 【一天一道LeetCode】#90. Subsets II
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
- iOS中GET 和 POST 数据请求
iOS中GET 和 POST 网络数据请求 同步请求和异步请求的差别: 1.同步请求,有主线程完成网路请求任务,在数据没有请求之前,用户的所有的交互事件应用都无法处理,会造成一种卡顿现象,影响用户体验 ...
- 【leetcode80】Reverse Vowels of a String(元音字母倒叙)
题目描述: 写一个函数,实现输入一个字符串,然后把其中的元音字母倒叙 注意 元音字母包含大小写,元音字母有五个a,e,i,o,u 原文描述: Write a function that takes a ...
- ant+eclipse知识点详解及使用案例
ant的优点和地位就不再阐述,下面直接上知识点: 在java中使用xml文件开发,有以下基本语法 (1)project:每个ant程序有且只有一个此标签,而且是类似于html的总标签,有name,de ...
- vs2010 单文档MFC 通过加载位图文件作为客户区背景
实现效果: 这个其实是一个非常常见的功能,大家都会考虑给自己简单的工程做一个背景界面.其实只要在view类中重载OnEraseBkgnd()这个函数就好了. 代码如下: BOOL CdddView:: ...
- 关于对数组和指针的测试与分析OC
前言: 这个笔试题想必很多小伙伴都很面熟把,差不多10个人有7个人不会做这道笔试题,或许有知道答案的,但是仅仅知道答案,心里还是一头雾水.如果你真的不会那就请认真看完本文学习一下吧! 错误想法: 有的 ...
- STL - 容器共性机制研究
C++模板是容器的概念. 理论提高:所有容器提供的都是值(value)语意,而非引用(reference)语意.容器执行插入元素的操作时,内部实施拷贝动作.所以STL容器内存储的元素必须能够被拷贝(必 ...