权威.NET多线程详解(源码示例)
.net多线程
.Net将操作系统的内存进一步细分为由system.appdomain表示的,成为应用程序区域的轻量级托管子进程。
一个或多个托管县城可以在同一个托管进程中的一个或任一数目应用程序域运行。
虽然每个应用程序域都是用耽搁线程启动的,但是该应用程序域中的代码可以创建附加应用程序域和附加线程。
其结果是托管县城可以在同一个非托管进程中的应用程序域自由移动。
多线程:处理的操作系统可以创建国歌进程中的多个线程同时执行。
在需要处理器时间的分割处理器时间,并轮流为每个线程分配处理器时间片。
当前执行的线程在其时间片结束时挂起,而另一个线程继续执行。
优点: 多个线程可以通过利用用户事件之间很小的时间段在后台处理数据达到同时工作的效果。
缺点:跟踪大量线程将占用大量处理器时间。
线程代码复杂。
资源共享会造成冲突,为了避免冲突必须对共享资源进行同步或控制共享资源的同步,避免死锁。
死锁:两个进程都停止响应并且都在等待对方的完成。
为阻止其他线程的相对小段任务处理多个线程并且不需要对这些人物执行任何调度。
使用ThreadPool类是一种简单的方式。
如果需要与用户界面交互的后台线程,提供了BackgroundWorker组件,该组件可以使用事件与用户界面线程跨线程进行通信。
异步编程:IO完成端口:适合大量的输入输出工作。
前台和后台线程:托管线程或者是后台线程,或者是前台线程。
后台线程不会使托管执行环境处于运行状态。
后台线程与前台线程是一样的。
一旦所有前台线程在托管进程中被停止,系统将停止所有后台线程并关闭。
BackgroundWorker允许在单独的专用线程上运行操作。
创建一个backgroundworker用于监听那些报告操作进度并在操作完成时发出信号的事件。
DoWork事件添加一个事件处理程序,启动操作用RunWorkerAsysnc。
若要受到进度更新通知请对ProgressChanged事件进行处理。
托管和非托管:所有的线程都是通过Thread类完成的,包括公共语言运行库创建的线程以及在运行库意外创建并进入托管环境已执行代码的线程。
.net 线程池的用法
.net 线程池的用法.NET Framework 提供了一个线程池(ThreadPool)来管理和提供线程。
线程池是一个用于执行异步操作的公共资源,可以有效地重用线程,提高性能,减少资源开销。
以下是.NET线程池的主要用法和示例:1. 提交工作项到线程池使用ThreadPool.QueueUserWorkItem方法可以将工作项(Work Item)提交到线程池执行。
using System;using System.Threading;class Program{static void Main(){// 提交工作项到线程池ThreadPool.QueueUserWorkItem(MyWorkMethod, "Hello, ThreadPool!");Console.WriteLine("Main thread does some work...");// 阻止主线程退出,以等待线程池中的工作项执行完成Console.ReadLine();}static void MyWorkMethod(object state){string message = (string)state;Console.WriteLine("Working in thread pool: " + message);}}2. 使用Task 进行异步操作.NET Framework 还引入了Task Parallel Library(TPL),通过Task.Run方法,你可以将方法包装成一个任务,并由线程池执行。
using System;using System.Threading;using System.Threading.Tasks;class Program{static void Main(){// 使用Task.Run 提交任务到线程池Task.Run(() => MyWorkMethod("Hello, ThreadPool!"));Console.WriteLine("Main thread does some work...");// 阻止主线程退出,以等待任务执行完成Console.ReadLine();}static void MyWorkMethod(string message){Console.WriteLine("Working in thread pool: " + message);}}3. 控制线程池中的线程数量可以使用ThreadPool.SetMinThreads和ThreadPool.SetMaxThreads方法来调整线程池中的最小和最大线程数。
net core源码解读
net core源码解读Net Core作为微软推出的跨平台开发框架,其源码的解读对于深入理解其内部机制和原理具有重要意义。
本文将对Net Core源码进行解读,帮助读者更好地理解这一框架。
一、源码概述Net Core源码主要包括.NET运行时、.NET标准库和 Core 等部分。
其中,.NET运行时是整个框架的核心,负责应用程序的加载、运行和管理。
.NET标准库是一组跨平台的类库,提供了丰富的API 用于开发各种应用程序。
Core则是基于.NET Core的Web开发框架,用于构建高效、可扩展的Web应用程序。
二、.NET运行时.NET运行时是Net Core框架的核心,它负责应用程序的加载、运行和管理。
在.NET运行时中,主要包括了垃圾回收器、JIT编译器、内存管理器、线程池等组件。
这些组件协同工作,为应用程序提供了稳定、高效的运行环境。
其中,垃圾回收器负责自动管理内存,防止内存泄漏和过度占用内存。
JIT编译器则负责将MSIL代码编译成本地代码,提高应用程序的运行效率。
内存管理器负责分配和释放内存,保证应用程序的内存安全。
线程池则提供了高效的线程复用机制,降低线程创建和销毁的开销。
三、.NET标准库.NET标准库是一组跨平台的类库,提供了丰富的API用于开发各种应用程序。
在.NET标准库中,主要包括了System命名空间下的众多类库,如System.Collections、System.IO、System.Threading等。
这些类库涵盖了常见的数据结构、文件操作、多线程编程等领域,为开发者提供了强大的支持。
四、 Core Core是基于.NET Core的Web开发框架,用于构建高效、可扩展的Web应用程序。
在 Core中,主要包括了Kestrel服务器、中间件、依赖注入等组件。
这些组件共同协作,实现了高效、安全的Web应用程序开发。
其中,Kestrel服务器是 Core内置的轻量级Web服务器,具有高效、可扩展的特点。
多线程之线程状态,状态切换种类及代码实例
多线程之线程状态,状态切换种类及代码实例线程的六种基本状态为:1.NEW(刚新建)2.Runable(可运⾏)3.Blocked(被阻塞)4.Waiting ( 等待 )5.Timed waiting (计时等待)6.Terminated (被终⽌,即执⾏完毕或线程死亡)以上为线程调度的基本知识需求,接下来进⼊线程的各个状态的流程细节。
线程执⾏实例:单线程,直接不中断执⾏,直⾄执⾏完毕public class Demo1 {static class Thread1 extends Thread{@Overridepublic void run() {int i=0;while (i++<10){System.out.println("now i = "+i);}}}public static void main(String[] args) {Thread1 t1 = new Thread1();t1.start();}}输出为:now i = 1now i = 2now i = 3now i = 4now i = 5now i = 6now i = 7now i = 8now i = 9now i = 10Process finished with exit code 0这是⼀个基本的线程执⾏,可以说是最最最最简单的线程执⾏,它没有线程切换的过程。
那么线程的切换有哪⼏种呢?⾸先直接上状态和状态切换总览图图看不清,可以在新⽹页中打开,⽬前没有找到好办法能让这么⼤内容的图⼆、线程切换的种类从上图看,有三种:第⼀种:由锁竞争带来的线程阻塞,如何重新启动被阻塞的线程第⼆种:在线程进⼊等待状态后,如何唤醒该线程第三种:在线程线程休眠时,如何重新唤醒该线程其中,第⼀种是在多条线程竞争锁产⽣的,是由于锁的机制⽽导致的线程问题,第⼆种和第三种是对某条线程独⽴进⾏的控制,是程序员⾃⼰主动控制的。
Visual Basic.net的多线程机制
级 线 程 的这 一 系列 操作 则 不 需要 系统 干 预 , 系统 也 不
会 感 知 到用 户线 程 的存 在 , 任何 线 程 的操 作 系统 都会
认为 是进 程 的操 作 。 不管 是那 种线 程 , 们都是 要并 但 它 发 执Байду номын сангаас 的 , 户 级线程 只 能在 自己的进程 中并 发执 行 , 用
i t no w c n s t e a u e h m u tt e di m e h im . The pa r ex ta e o t e s r t e , f c in nd s ge f he ulihr a lihr a ng c an s pe pa i t s n h t uc ur un to a u a o t m tt e d m e ha s . Fis ,i e n xa p e s h a sng V B6 nd V B. e o c l ult he r n i e f r ul ton t a ie t c nim rt tus s a e m l uc s u i .0 a n t t ac a e t u tm or acic a i O pr ctc he
维普资讯
第 2 O卷
第 1 1期
电 脑 开 发 与 应 用
文 覃 编 号 :0 3 5 5 ( 0 7 1 - 0 3 0 1 0 — 8 0 2 0 ) 10 6 — 3
Viu l ai. e 的 多线 程机 制 sa sc n t B
M u tt e di e h ni m f Vi u lBa i . t lihr a ng M c a s o s a s c ne
.net多线程的使用(Thread)
.net多线程的使⽤(Thread)上篇中篇多线程的使⽤(Thread)下篇 net 任务⼯⼚实现异步多线程Thread多线程概述上⼀篇我们介绍了net 的同步与异步,我们异步演⽰的时候使⽤的是委托多线程来实现的。
今天我们来细细的剖析下多线程。
多线程的优点:可以同时完成多个任务;可以使程序的响应速度更快;可以让占⽤⼤量处理时间的任务或当前没有进⾏处理的任务定期将处理时间让给别的任务;可以随时停⽌任务;可以设置每个任务的优先级以优化程序性能。
然⽽,多线程虽然有很多优点,但是也必须认识到多线程可能存在影响系统性能的不利⽅⾯,才能正确使⽤线程。
弊端主要有如下⼏点:(1)线程也是程序,所以线程需要占⽤内存,线程越多,占⽤内存也越多。
(2)多线程需要协调和管理,所以需要占⽤CPU时间以便跟踪线程[时间空间转换,简称时空转换]。
(3)线程之间对共享资源的访问会相互影响,必须解决争⽤共享资源的问题。
(4)线程太多会导致控制太复杂,最终可能造成很多程序缺陷。
当启动⼀个可执⾏程序时,将创建⼀个主线程。
在默认的情况下,C#程序具有⼀个线程,此线程执⾏程序中以Main⽅法开始和结束的代码,Main()⽅法直接或间接执⾏的每⼀个命令都有默认线程(主线程)执⾏,当Main()⽅法返回时此线程也将终⽌。
⼀个进程可以创建⼀个或多个线程以执⾏与该进程关联的部分程序代码。
在C#中,线程是使⽤Thread类处理的,该类在System.Threading命名空间中。
使⽤Thread类创建线程时,只需要提供线程⼊⼝,线程⼊⼝告诉程序让这个线程做什么。
通过实例化⼀个Thread类的对象就可以创建⼀个线程。
多线程Thread上⼀节我们通过了线程的异步了解了线程的等待和线程回调的区别、学习了不卡主线程的原理。
这⾥我们简单学习下 Thread 类的使⽤.我们分别让主线程和⼦线程循环输出 1-100,我们来看下结果。
Thread类接收⼀个ThreadStart委托或ParameterizedThreadStart委托的构造函数,该委托包装了调⽤Start⽅法时由新线程调⽤的⽅法,⽰例代码如下:Thread thread=new Thread(new ThreadStart(method));//创建线程thread.Start(); //启动线程1.线程的⽆序性质Thread t = new Thread(()=> {for (int i = 0; i < 100; i++){Console.WriteLine($"我是⼦线程({i})~~~~");}});// 参数 ThreadStart 是⼀个委托类型的。
.net 线程执行方法
在.NET中,可以使用多种方式来执行多线程。
以下是几种常用的方法:1. 使用`System.Threading.Thread`类:可以创建新的线程并执行代码块。
例如:```csharpusing System.Threading;public void StartThread(){Thread newThread = new Thread(() =>{// 在新线程中执行的代码});newThread.Start();}```2. 使用`System.Threading.Task`类:Task是.NET 4.0引入的,用于表示异步操作。
可以使用`Task.Run()`方法来创建并启动新线程。
例如:```csharpusing System.Threading.Tasks;public async Task StartTask(){await Task.Run(() =>{// 在新线程中执行的代码});}```3. 使用`Parallel.For`或`Parallel.ForEach`方法:这些方法可以在多个线程上并行执行代码块。
例如:```csharpusing System.Threading.Tasks;using System.Threading;using System.Threading.Tasks.Parallel;public void StartParallelLoop(){Parallel.For(0, 10, i =>{// 在多个线程上并行执行的代码});}```需要注意的是,多线程编程需要谨慎处理线程同步和资源访问问题,以避免出现竞态条件和死锁等问题。
可以使用锁、信号量、事件等机制来控制线程之间的同步和通信。
.net 多线程异步编程详解
.NET 多线程异步编程是一种用于开发并发性应用程序的重要技术,允许应用程序同时执行多个任务而无需阻塞主线程。
在.NET框架中,你可以使用async和await关键字来编写异步代码,这些关键字使异步编程变得更加容易。
下面是.NET多线程异步编程的详细解释:async 和await 关键字:async 关键字用于标记一个方法,指示该方法包含异步操作。
异步方法可以在执行过程中让线程释放并继续执行其他工作。
await 关键字用于指示在异步方法中等待异步操作完成。
它可以应用于异步任务,如异步方法、任务、线程池工作项等。
任务(Task)和任务运行(Task.Run):Task 是.NET框架中表示异步操作的一种抽象类型。
你可以使用Task来创建异步操作,然后使用await等待任务完成。
Task.Run 方法用于在后台线程上执行指定的方法。
它可以用于将同步代码包装成异步任务。
异步编程模型(APM)和事件异步模式(EAP):在.NET中,还存在一些传统的异步编程模型,如异步编程模型(APM)和事件异步模式(EAP)。
虽然它们已经过时,但仍然存在于某些旧代码中。
异步异常处理:在异步编程中,异常处理变得更加复杂。
你可以使用try-catch块来捕获和处理异步操作中的异常,也可以使用Task.Exception属性来访问异常信息。
并行编程:在.NET中,你可以使用Parallel类和PLINQ(Parallel Language Integrated Query)来执行并行操作。
这允许你同时处理大量数据,提高应用程序的性能。
取消异步操作:你可以使用CancellationToken来取消异步操作,以避免资源浪费和不必要的执行。
异步编程最佳实践:避免在异步方法中使用阻塞操作,如Task.Wait或Thread.Sleep。
将异步操作封装在try-catch块中,以处理潜在的异常。
考虑性能和资源消耗,避免创建过多的异步任务。
一起谈.NET技术,4.0中的并行计算和多线程详解(一)
⼀起谈.NET技术,4.0中的并⾏计算和多线程详解(⼀) 并⾏计算部分 沿⽤微软的写法,System.Threading.Tasks.::.Parallel类,提供对并⾏循环和区域的⽀持。
我们会⽤到的⽅法有For,ForEach,Invoke。
⼀、简单使⽤ ⾸先我们初始化⼀个List⽤于循环,这⾥我们循环10次。
(后⾯的代码都会按这个标准进⾏循环)1. Program.Data = new List<int>();2. for (int i = 0; i < 10; i++)3. {4. Data.Add(i);5. } 下⾯我们定义4个⽅法,分别为for,foreach,并⾏For,并⾏ForEach。
并测试他们的运⾏时长。
三、并⾏循环中为数组/集合添加项 上⾯的应⽤场景其实并不是⾮常多见,毕竟只是为了遍历⼀个数组内的资源,我们更多的时候是为了遍历资源,找到我们所需要的。
那么请继续看。
下⾯是我们⼀般会想到的写法: 这是因为List 是⾮线程安全的类,我们需要使⽤System.Collections.Concurrent 命名空间下的类型来⽤于并⾏循环体内。
类说明BlockingCollection<T>为实现 IProducerConsumerCollection<T> 的线程安全集合提供阻⽌和限制功能。
ConcurrentBag<T>表⽰对象的线程安全的⽆序集合。
ConcurrentDictionary<TKey,TValue>表⽰可由多个线程同时访问的键值对的线程安全集合。
ConcurrentQueue<T>表⽰线程安全的先进先出 (FIFO) 集合。
ConcurrentStack<T>表⽰线程安全的后进先出 (LIFO) 集合。
OrderablePartitioner<TSource>表⽰将⼀个可排序数据源拆分成多个分区的特定⽅式。
c#(asp.net)多线程示例,用于同时处理多个任务
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Threading; using System.Web.UI.WebControls;
public partial class muti_thread : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
Thread Thread1 = new Thread(new ThreadStart(CalcSum)); Thread Thread2 = new Thread(new ThreadStart(CalcGap));
//求差方法 protected void CalcGap() {
long gap = 0; for (long i = 100; i >= 0; i--) {
gap = i - 1; Response.Write(string.Format("Thread2-->i={0}:gap={1}<br/>", i, gap)); Response.Flush(); System.Threading.Thread.Sleep(1000); } } }
基于c开发的超强工具类集合涵盖了日常bs或cs开发的诸多方面包含上百个常用封装类数据库操作类全面支持mysqlaccessoraclesqlserversqlite等数据库常用字符串处理类内存容器类sessioncookiecache类config配置文件帮助类数据类型转换类进制转换类时间日期帮助类数据加密解密类文件目录操作类文件下载类ftp操作类图片上传下载类图片常用处理类翻转模糊水印缩略等json辅助类log日志类http封装类email邮件封装类nopi操作类无依赖office组件实现execl导入导出利器execlcsv操作类until常用工具类数据分页类远程采集类js封装类reg正则验证类request请求类随机数生成类序列化反序列化封装类xml操作类zip压缩和解压类等等等
.NET面试题系列(六)多线程
.NET⾯试题系列(六)多线程
1.多线程的三个特性:原⼦性、可见性、有序性
原⼦性:是指⼀个操作是不可中断的。
即使是多个线程⼀起执⾏的时候,⼀个操作⼀旦开始,就不会被其他线程⼲扰。
⽐如,对于⼀个静态全局变量int i,两个线程同时对它赋值,线程A给他赋值为1,线程B给他赋值为-1。
那么不管这两个线程
以何种⽅式。
何种步调⼯作,i的值要么是1,要么是-1.线程A和线程B之间是没有⼲扰的。
这就是原⼦性的⼀个特点,不可被中断。
可见性:是指当⼀个线程修改了某⼀个共享变量的值,其他线程是否能够⽴即知道这个修改。
显然,对于串⾏来说,可见性问题是不存在的。
有序性:在并发时,程序的执⾏可能会出现乱序。
给⼈的直观感觉就是:写在前⾯的代码,会在后⾯执⾏。
有序性问题的原因是因为程序在
执⾏时,可能会进⾏指令重排,重排后的指令与原指令的顺序未必⼀致。
ASP.NET多线程编程(一)
进程举例
设一个进程要完成两个任务:任务1和任务2, 并且任务1 要经历: A1->B1->C1三个步骤才能完成;任务2要经历: A2->B2->C2三个步骤才能完成。
• 也不例外,它在每个辅助进程中使用多个线程来为 请求提供服务。
• 使用进程范围的 CLR 线程池为请求提供服务。该 池的大小可以在 machine.config 的 processModel 元素中进行 配置,并且被默认设置为 25 个辅助线程和 25 个 I/O 线程。
用目标方法。如果编译器支持异步委托,则它将生成 该调用方法以及 BeginInvoke 和 EndInvoke 方法。 • 如果调用 BeginInvoke 方法,则公共语言运行库将 对请求进行排队并立即返回到调用方。将对来自线程 池的线程调用该目标方法。提交请求的原始线程自由 地继续与目标方法并行执行,该目标方法是对线程池 线程运行的 • 在回调中,使用 EndInvoke 方法来获取返回值和输 入/输出参数。如果没有对 BeginInvoke 指定回调, 则可以在提交请求的原始线程上使用 EndInvoke。
System.Threading
• 提供一些使得可以进行多线程编程的类和 接口。此命名空间包括管理线程组的 ThreadPool 类、使得可以在指定的时间后 调用委托的 Timer 类以及用于同步互斥线 程的 Mutex 类。System.Threading 还提 供用于线程调度、等待通知和死锁解析的 类。
• 使用应用程序域:
– 能够在不停止整个进程的情况下停止单个应用程序。 – 在一个应用程序中运行的代码不能直接访问其他应用程序中的代
一个基于多线程的.NET开发应用实例研究
fr r o te a t a f c v n s f rn a t n I( o mar r h cu le e t e e so t sc o pD 慰 I i n t me o f ae ss ms o t trsa c esf m o s c a d O  ̄ f i a is n u i t fs t r t .D e e r h r o d me t n — i ow ye Ne r i v r a a e ma e e tn ie rsa c e n ti ed es sh v d xe v e e r h s o sf l .Re rn i uk fpa t a x e e c s h a r rt e eai sh w t e e s h i f e cn b ls o r c c l p r n e .tep p f l g n rl e o d - e g i e i e i y s z o
维普资讯
20 年 第 7期 O6
文章 编 号 : 0-4 520 )7090 1 62 7(06 0.5.3 0
计 算 机 与 现 代 化 J U NI Y XA D IU I AJ S U IN AH A
总第 11 3 期
一
个 基 于多 线 程 的 . E N T开发应 用 实 例研 究
中图分类号:P 9 131 文献标识码 : A
Re e r h o n p iaa v l pn sa c n a Ap l t n o li l r a s i tNe o r m De eo ig ci
.
1 . e 中任务 、 Nt 过程和线程概念
众所周知 , 计算 的资源是有限的, 我们必须将更 多的任务在同一时间内完成而不是将其排序 , 这往往 会使工作变得很漫长而降低 了工作效率 , 当然计算机 处理事务的同时性和人处理事情 的同时性是很相似
net core 源码解读
Net Core是微软推出的全新的开源跨评台框架,它采用了全新的模块化和开放源代码的设计,为开发人员提供了更加强大和灵活的功能。
Net Core的开源代码也为开发人员提供了更多学习和深入了解的机会。
1. Net Core的架构设计Net Core的架构设计经过了精心的思考和设计,其采用了模块化的架构,使得开发人员可以根据自己的需求进行定制化的开发。
Net Core也采用了更加轻量级和高效的设计理念,可以在不同的评台上进行快速部署和运行。
2. Net Core的核心组件Net Core包括了许多核心组件,例如.NET Runtime,库和SDK等。
这些组件为开发人员提供了丰富的功能和工具,可以帮助开发人员快速完成开发任务,并且可以在多种评台上运行。
3. Net Core的源码结构Net Core的源码结构清晰,模块化程度高,其中包含了许多关键组件的源代码,例如 Core、Entity Framework Core等。
通过分析这些源代码,开发人员可以更加深入地了解Net Core框架的实现原理和内部运行机制。
4. Net Core的编译与调试Net Core的源码可以通过Visual Studio等IDE进行编译和调试,开发人员可以方便地对Net Core进行二次开发并调试。
开发人员还可以通过查看源码的方式深入了解.Net Core框架的各个组件的实现细节。
5. Net Core的社区贡献Net Core是一个开源项目,拥有一个庞大的开发者社区。
许多开发人员都积极参与到Net Core的开发和贡献中,不断完善和优化Net Core框架。
通过参与社区贡献,开发人员可以与其他开发者交流学习,共同推动Net Core框架的发展。
6. Net Core的未来展望随着.Net Core的不断发展壮大,它将会成为跨评台开发的核心框架之一,并且在移动开发和云计算领域有着广阔的应用前景。
未来,Net Core将会继续引领着开发技术的发展,为开发人员提供更加强大和灵活的工具和评台。
高级多线程编程
.NET多线程编程在.NET多线程编程这个系列我们将一起来探讨多线程编程的各个方面。
在文的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述.NET平台上多线程编程的知识,诸如System.Threading命名空间的重要类以及方法,并就一些例子程序来做说明。
一.多任务和多线程引言早期的计算硬件十分复杂,但是操作系统执行的功能确十分的简单。
那个时候的操作系统在任一时间点只能执行一个任务,也就是同一时间只能执行一个程序。
多个任务的执行必须得轮流执行,在系统里面进行排队等候。
由于计算机的发展,要求系统功能越来越强大,这个时候出现了分时操作的概念:每个运行的程序占有一定的处理机时间,当这个占有时间结束后,在等待队列等待处理器资源的下一个程序就开始投入运行。
注意这里的程序在占有一定的处理器时间后并没有运行完毕,可能需要再一次或多次分配处理器时间。
那么从这里可以看出,这样的执行方式显然是多个程序的并行执行,但是在宏观上,我们感觉到多个任务是同时执行的,因此多任务的概念就诞生了。
每个运行的程序都有自己的内存空间,自己的堆栈和环境变量设置。
每一个程序对应一个进程,代表着执行一个大的任务。
一个进程可以启动另外一个进程,这个被启动的进程称为子进程。
父进程和子进程的执行只有逻辑上的先后关系,并没有其他的关系,也就是说他们的执行是独立的。
但是,可能一个大的程序(代表着一个大的任务),可以分割成很多的小任务,为了功能上的需要也有可能是为了加快运行的速度,可能需要同一时间执行多个任务(每个任务分配一个多线程来执行相应的任务)。
举个例子来说,你正在通过你的web浏览器查看一些精彩的文章,你需要把好的文章给下载下来,可能有些非常精彩的文章你需要收藏起来,你就用你的打印机打印这些在线的文章。
在这里,浏览器一边下载HTML格式的文章,一边还要打印文章。
这就是一个程序同时执行多个任务,每个任务分配一个线程来完成。
.net多线程传参数
.net多线程传参数 Thread上执⾏的⽅法的委托ThreadStart不能带参数,ParameterizedThreadStart可以带参数using System;using System.Threading;public class Work{public static void Main(){// To start a thread using a shared thread procedure, use// the class name and method name when you create the// ParameterizedThreadStart delegate.//Thread newThread = new Thread(new ParameterizedThreadStart(Work.DoWork));// Use the overload of the Start method that has a// parameter of type Object. You can create an object that// contains several pieces of data, or you can pass any// reference type or value type. The following code passes// the integer value 42.//newThread.Start(42);// To start a thread using an instance method for the thread// procedure, use the instance variable and method name when// you create the ParameterizedThreadStart delegate.//Work w = new Work();newThread = new Thread(new ParameterizedThreadStart(w.DoMoreWork));// Pass an object containing data for the thread.//newThread.Start("The answer.");}public static void DoWork(object data){Console.WriteLine("Static thread procedure. Data='{0}'",data);}public void DoMoreWork(object data){Console.WriteLine("Instance thread procedure. Data='{0}'",data);}}/* This code example produces the following output (the orderof the lines might vary):Static thread procedure. Data='42'Instance thread procedure. Data='The answer'*/。
使用.Net实现多线程经验总结
使⽤.Net实现多线程经验总结1.简述 ⼀般⼀个程序⼀个进程,代码是存在进程中的,进程本⾝不执⾏代码, 执⾏代码的是线程。
⼀般⼀个进程⾥就⼀个线程。
(⼀个商店就⼀个⽼板娘。
) 进程就是在内存中开辟了⼀个空间。
代码,图⽚。
等就存在这个空间⾥。
代码线程去执⾏。
默认只有⼀个线程。
复制代码代码如下:systerm.threading //线程操作的类在这个命名空间下。
2.前台线程与后台线程。
开启⼀个线程,就是创建⼀个线程对象即可。
线程默认情况下都是前台线程。
要把所有的前台线程执⾏完后,程序才会退出。
进程⾥默认的线程叫主线程或者默认线程,或UI线程。
后台线程,只要所有的前台线程结束,所有的后台线程就直接结束。
复制代码代码如下:Thread th = new Thread(Sum); ="线程1"; 给线程取名。
调试的时候可以在输出中看到具体名称。
th.IsBackground = true;th.Start();th.Abort(); 强⾏终⽌线程。
Thread.Sleep(1000); 暂停线程,单位是毫秒Thread cuTh = Thread.CurrentThread 得到当前线程的引⽤。
Thread类型。
TextBox.CheckForIllegalCrossThreadCalls = false; //关闭空间的跨线程访问检查。
否则会出现如下错误3.线程重⼊ 同⼀个进程中的多个线程之间可以“并发”执⾏。
多个线程访问同⼀资源,可能造成不同步的情况,这个叫做线程重⼊。
应对此情况,可加锁处理。
复制代码代码如下:private void CountNum(){lock (this){for (int i = 0; i < 10000; i++){int num = int.Parse(textBox1.Text.Trim());num++;textBox1.Text = num.ToString();}}}4.线程对象本质(委托) 4.1 ⽆参⽅法 需要传⼀个委托对象。
.NET异步和多线程系列(一)
.NET异步和多线程系列(⼀)本系列将和⼤家分享.Net中的异步多线程,本⽂是该系列的开篇。
⾸先来看些概念:进程:计算机概念,虚拟的概念,程序在服务器运⾏时占据全部计算资源的总和,我们给它起个名字叫进程。
线程:计算机概念,虚拟的概念,进程在响应操作时最⼩单位,也包含CPU 内存⽹络硬盘IO。
多线程:计算机概念,⼀个进程有多个线程同时运⾏。
进程与线程的区别: 1、线程是程序执⾏的最⼩单位,⽽进程是操作系统分配资源的最⼩单位; 2、⼀个进程由⼀个或多个线程组成,线程是⼀个进程中代码的不同执⾏路线。
3、进程之间相互独⽴,但同⼀进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及⼀些进程级的资源(如打开⽂件和信号等),某进程内的线程在其他进程不可见; 4、调度和切换:线程上下⽂切换⽐进程上下⽂切换要快得多。
5、包含关系:没有线程的进程可以看作是单线程的。
如果⼀个进程内有多个线程,则执⾏过程不是⼀条线的,⽽是多条线(线程)共同完成的;线程是进程的⼀部分,所以线程也被称为轻权进程或者轻量级进程。
线程和进程关系⽰意图:总之,线程和进程都是⼀种抽象的概念,线程是⼀种⽐进程还⼩的抽象,线程和进程都可⽤于实现并发。
在早期的操作系统中并没有线程的概念,进程是能拥有资源和独⽴运⾏的最⼩单位,也是程序执⾏的最⼩单位,它相当于⼀个进程⾥只有⼀个线程,进程本⾝就是线程。
所以线程有时被称为轻量级进程。
后来,随着计算机的发展,对多个任务之间上下⽂切换的效率要求越来越⾼,就抽象出⼀个更⼩的概念——线程,⼀般⼀个进程会有多个(也可以是⼀个)线程。
任务调度:⼤部分操作系统的任务调度是采⽤时间⽚轮转的抢占式调度⽅式,也就是说⼀个任务执⾏⼀⼩段时间后强制暂停去执⾏下⼀个任务,每个任务轮流执⾏。
任务执⾏的⼀⼩段时间叫做时间⽚,任务正在执⾏时的状态叫运⾏状态,任务执⾏⼀段时间后强制暂停去执⾏下⼀个任务,被暂停的任务就处于就绪状态,等待下⼀个属于它的时间⽚的到来。
VB_.NET多线程编程的详细说明(完整版)
VB .NET多线程编程的详细说明介绍传统的Visual Basic开发人员已经建立了同步应用程序,在这些程序中事务按顺序执行。
尽管由于多个事务多多少少地同时运行使多线程应用程序效率更高,但是使用先前版本的Visual Basic很难建立这类程序。
多线程程序是可行的,因为操作系统是多任务的,它有模拟同一时刻运行多个应用程序的能力。
尽管多数个人计算机只有一个处理器,但是现在的操作系统还是通过在多个执行代码片断之间划分处理器时间提供了多任务。
线程可能是整个应用程序,但通常是应用程序可以单独运行的一个部分。
操作系统根据线程的优先级和离最近运行的时间长短给每一个线程分配处理时间。
多线程对于时间密集型事务(例如文件输入输出)应用程序的性能有很大的提高。
但是也有必须细心的地方。
尽管多线程能提高性能,但是每个线程还是需要用附加的内存来建立和处理器时间来运行,建立太多的线程可能降低应用程序的性能。
当设计多线程应用程序时,应该比较性能与开销。
多任务成为操作系统的一部分已经很久了。
但是直到最近Visual Basic程序员才能使用无文档记录特性(undocumented)或者间接使用COM组件或者操作系统的异步部分执行多线程事务。
.NET框架组件为开发多线程应用程序,在System.Threading名字空间中提供了全面的支持。
本文讨论多线程的好处以及怎样使用Visual Basic .NET开发多线程应用程序。
尽管Visual Basic .NET和.NET框架组件使开发多线程应用程序更容易,但是本文作了调整使其适合高级读者和希望从早期Visual Basic转移到Visual Basic .NET的开发人员。
多线程处理的优点尽管同步应用程序易于开发,但是它们的性能通常比多线程应用程序低,因为一个新的事务必须等待前面的事务完成后才能开始。
如果完成某个同步事务的时间比预想的要长,应用程序可能没有响应。
多线程处理可以同时运行多个过程。
.NET异步和多线程系列(四)-多线程异常处理、线程取消、多线程的临时变量问题、线程安全和。。。
.NET异步和多线程系列(四)-多线程异常处理、线程取消、多线程的临时变量问题、线程安全和。
本⽂是.NET异步和多线程系列第四章,主要介绍的是多线程异常处理、线程取消、多线程的临时变量问题、线程安全和锁lock等。
⼀、多线程异常处理多线程⾥⾯抛出的异常,会终结当前线程,但是不会影响别的线程。
那线程异常哪⾥去了?被吞了。
假如想获取异常信息,这时候要怎么办呢?下⾯来看下其中的⼀种写法(不推荐):///<summary>/// 1 多线程异常处理和线程取消/// 2 多线程的临时变量/// 3 线程安全和锁lock///</summary>private void btnThreadCore_Click(object sender, EventArgs e){Console.WriteLine($"****************btnThreadCore_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +$"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");#region多线程异常处理{try{List<Task> taskList = new List<Task>();for (int i = 0; i < 100; i++){string name = $"btnThreadCore_Click_{i}";taskList.Add(Task.Run(() =>{if (name.Equals("btnThreadCore_Click_11")){throw new Exception("btnThreadCore_Click_11异常");}else if (name.Equals("btnThreadCore_Click_12")){throw new Exception("btnThreadCore_Click_12异常");}else if (name.Equals("btnThreadCore_Click_38")){throw new Exception("btnThreadCore_Click_38异常");}Console.WriteLine($"This is {name}成功 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");}));}//多线程⾥⾯抛出的异常,会终结当前线程,但是不会影响别的线程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录本文档网上收集,如果出现版权问题,请及时的联系我,我将删除之!1基础篇∙怎样创建一个线程∙受托管的线程与Windows线程∙前台线程与后台线程∙名为BeginXXX和EndXXX的方法是做什么用的∙异步和多线程有什么关联WinForm多线程编程篇∙我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决?∙Invoke,BeginInvoke干什么用的,内部是怎么实现的∙每个线程都有消息队列吗?∙为什么Winform不允许跨线程修改UI线程控件的值∙有没有什么办法可以简化WinForm多线程的开发线程池∙线程池的作用是什么?∙所有进程使用一个共享的线程池,还是每个进程使用独立的线程池?∙为什么不要手动线程池设置最大值?∙.Net线程池有什么不足?同步∙CLR怎样实现lock(obj)锁定?∙WaitHandle是什么,他和他的派生类怎么使用∙什么是用双锁实现Singleton,为什么要这样做,为什么有人说双锁检验是不安全的∙互斥对象(Mutex)、事件(Event)对象与lock语句的比较什么时候需要锁定∙只有共享资源才需要锁定∙把锁定交给数据库∙了解你的程序是怎么运行的∙业务逻辑对事务和线程安全的要求∙计算一下冲突的可能性∙请多使用lock,少用MutexWeb和IIS∙应用程序池,WebApplication,和线程池之间有什么关系∙Web页面怎么调用异步WebService基础篇怎样创建一个线程一)使用Thread类ThreadStart threadStart=new ThreadStart(Calculate);//通过ThreadStart委托告诉子线程讲执行什么方法,这里执行一个计算圆周长的方法Thread thread=new Thread(threadStart);thread.Start(); //启动新线程public void Calculate(){double Diameter=0.5;Console.Write("The perimeter Of Circle with a Diameter of {0} is {1}"Diameter,Diameter*Math.PI); }二)使用Delegate.BeginInvokedelegate double CalculateMethod(double Diameter); //申明一个委托,表明需要在子线程上执行的方法的函数签名static CalculateMethod calcMethod = new CalculateMethod(Calculate);//把委托和具体的方法关联起来static void Main(string[] args){//此处开始异步执行,并且可以给出一个回调函数(如果不需要执行什么后续操作也可以不使用回调)calcMethod.BeginInvoke(5, new AsyncCallback(TaskFinished), null);Console.ReadLine();}//线程调用的函数,给出直径作为参数,计算周长public static double Calculate(double Diameter){return Diameter * Math.PI;}//线程完成之后回调的函数public static void TaskFinished(IAsyncResult result){double re = 0;re = calcMethod.EndInvoke(result);Console.WriteLine(re);}三)使用ThreadPool.QueueworkItemWaitCallback w = new WaitCallback(Calculate);//下面启动四个线程,计算四个直径下的圆周长ThreadPool.QueueUserWorkItem(w, 1.0);ThreadPool.QueueUserWorkItem(w, 2.0);ThreadPool.QueueUserWorkItem(w, 3.0);ThreadPool.QueueUserWorkItem(w, 4.0);public static void Calculate(double Diameter){return Diameter * Math.PI;}下面两条来自于/tonyman/archive/2007/09/13/891912. html受托管的线程与Windows线程必须要了解,执行.NET应用的线程实际上仍然是Windows线程。
但是,当某个线程被CLR所知时,我们将它称为受托管的线程。
具体来说,由受托管的代码创建出来的线程就是受托管的线程。
如果一个线程由非托管的代码所创建,那么它就是非托管的线程。
不过,一旦该线程执行了受托管的代码它就变成了受托管的线程。
一个受托管的线程和非托管的线程的区别在于,CLR将创建一个System.Threading.Thread类的实例来代表并操作前者。
在内部实现中,CLR将一个包含了所有受托管线程的列表保存在一个叫做ThreadStore地方。
CLR确保每一个受托管的线程在任意时刻都在一个AppDomain中执行,但是这并不代表一个线程将永远处在一个AppDomain中,它可以随着时间的推移转到其他的AppDomain中。
从安全的角度来看,一个受托管的线程的主用户与底层的非托管线程中的Windows主用户是无关的。
前台线程与后台线程启动了多个线程的程序在关闭的时候却出现了问题,如果程序退出的时候不关闭线程,那么线程就会一直的存在,但是大多启动的线程都是局部变量,不能一一的关闭,如果调用Thread.CurrentThread.Abort()方法关闭主线程的话,就会出现ThreadAbortException 异常,因此这样不行。
后来找到了这个办法:Thread.IsBackground 设置线程为后台线程。
msdn对前台线程和后台线程的解释:托管线程或者是后台线程,或者是前台线程。
后台线程不会使托管执行环境处于活动状态,除此之外,后台线程与前台线程是一样的。
一旦所有前台线程在托管进程(其中.exe 文件是托管程序集)中被停止,系统将停止所有后台线程并关闭。
通过设置Thread.IsBackground 属性,可以将一个线程指定为后台线程或前台线程。
例如,通过将Thread.IsBackground 设置为true,就可以将线程指定为后台线程。
同样,通过将IsBackground 设置为false,就可以将线程指定为前台线程。
从非托管代码进入托管执行环境的所有线程都被标记为后台线程。
通过创建并启动新的Thread 对象而生成的所有线程都是前台线程。
如果要创建希望用来侦听某些活动(如套接字连接)的前台线程,则应将Thread.IsBackground 设置为true,以便进程可以终止。
所以解决办法就是在主线程初始化的时候,设置:Thread.CurrentThread.IsBackground = true;这样,主线程就是后台线程,在关闭主程序的时候就会关闭主线程,从而关闭所有线程。
但是这样的话,就会强制关闭所有正在执行的线程,所以在关闭的时候要对线程工作的结果保存。
经常看到名为BeginXXX和EndXXX的方法,他们是做什么用的这是.net的一个异步方法名称规范.Net 在设计的时候为异步编程设计了一个异步编程模型(APM),这个模型不仅是使用.NET的开发人员使用,.Net内部也频繁用到,比如所有的Stream 就有BeginRead,EndRead,Socket,WebRequet,SqlCommand都运用到了这个模式,一般来讲,调用 BegionXXX的时候,一般会启动一个异步过程去执行一个操作,EndEnvoke可以接收这个异步操作的返回,当然如果异步操作在 EndEnvoke调用的时候还没有执行完成,EndInvoke会一直等待异步操作完成或者超时.Net的异步编程模型(APM)一般包含BeginXXX,EndXXX,IAsyncResult这三个元素,BeginXXX方法都要返回一个IAsyncResult,而EndXXX都需要接收一个IAsyncResult作为参数,他们的函数签名模式如下IAsyncResult BeginXXX(...);<返回类型> EndXXX(IAsyncResult ar);BeginXXX 和EndXXX中的XXX,一般都对应一个同步的方法,比如FileStream的Read方法是一个同步方法,相应的BeginRead(), EndRead()就是他的异步版本,HttpRequest有GetResponse来同步接收一个响应,也提供了BeginGetResponse 和 EndGetResponse这个异步版本,而IAsynResult是二者联系的纽带,只有把BeginXXX所返回的IAsyncResult传给对应的EndXXX,EndXXX才知道需要去接收哪个BeginXXX发起的异步操作的返回值。
这个模式在实际使用时稍显繁琐,虽然原则上我们可以随时调用EndInvoke来获得返回值,并且可以同步多个线程,但是大多数情况下当我们不需要同步很多线程的时候使用回调是更好的选择,在这种情况下三个元素中的IAsynResult就显得多余,我们一不需要用其中的线程完结标志来判断线程是否成功完成(回调的时候线程应该已经完成了),二不需要他来传递数据,因为数据可以写在任何变量里,并且回调时应该已经填充,所以可以看到微软在新的.Net Framework 中已经加强了对回调事件的支持,这总模型下,典型的回调程序应该这样写a.DoWork+=new SomeEventHandler(Caculate);a.CallBack+=new SomeEventHandler(callback);a.Run();(注:我上面讲的是普遍的用法,然而BeginXXX,EndXXX仅仅是一种模式,而对这个模式的实现完全取决于使用他的开发人员,具体实现的时候你可以使用另外一个线程来实现异步,也可能使用硬件的支持来实现异步,甚至可能根本和异步没有关系(尽管几乎没有人会这样做)-----比如直接在Beginxxx 里直接输出一个"Helloworld",如果是这种极端的情况,那么上面说的一切都是废话,所以上面的探讨并不涉及内部实现,只是告诉大家微软的模式,和框架中对这个模式的经典实现)异步和多线程有什么关联有一句话总结的很好:多线程是实现异步的一种手段和工具我们通常把多线程和异步等同起来,实际是一种误解,在实际实现的时候,异步有许多种实现方法,我们可以用进程来做异步,或者使用纤程,或者硬件的一些特性,比如在实现异步IO的时候,可以有下面两个方案:1)可以通过初始化一个子线程,然后在子线程里进行IO,而让主线程顺利往下执行,当子线程执行完毕就回调2)也可以根本不使用新线程,而使用硬件的支持(现在许多硬件都有自己的处理器),来实现完全的异步,这是我们只需要将IO请求告知硬件驱动程序,然后迅速返回,然后等着硬件IO就绪通知我们就可以了实际上DotNet Framework里面就有这样的例子,当我们使用文件流的时候,如果制定文件流属性为同步,则使用BeginRead进行读取时,就是用一个子线程来调用同步的Read方法,而如果指定其为异步,则同样操作时就使用了需要硬件和操作系统支持的所谓IOCP的机制WinForm多线程编程篇我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决?在WinForm中使用多线程时,常常遇到一个问题,当在子线程(非UI线程)中修改一个控件的值:比如修改进度条进度,时会抛出如下错误Cross-thread operation not valid: Control 'XXX' accessed from a thread other than the thread it was created on.在VS2005 或者更高版本中,只要不是在控件的创建线程(一般就是指UI主线程)上访问控件的属性就会抛出这个错误,解决方法就是利用控件提供的Invoke 和 BeginInvoke把调用封送回UI线程,也就是让控件属性修改在UI线程上执行,下面列出会报错的代码和他的修改版本ThreadStart threadStart=new ThreadStart(Calculate);//通过ThreadStart委托告诉子线程讲执行什么方法Thread thread=new Thread(threadStart);thread.Start();public void Calculate(){double Diameter=0.5;double result=Diameter*Math.PI;CalcFinished(result);//计算完成需要在一个文本框里显示}public void CalcFinished(double result){this.TextBox1.Text=result.ToString();//会抛出错误}上面加粗的地方在debug的时候会报错,最直接的修改方法是修改Calculate 这个方法如下delegate void changeText(double result);public void Calculate(){double Diameter=0.5;double result=Diameter*Math.PI;this.BeginInvoke(new changeText(CalcFinished),t.Result);//计算完成需要在一个文本框里显示}这样就ok了,但是最漂亮的方法是不去修改Calculate,而去修改CalcFinished 这个方法,因为程序里调用这个方法的地方可能很多,由于加了是否需要封送的判断,这样修改还能提高非跨线程调用时的性能delegate void changeText(double result);public void CalcFinished(double result){if(this.InvokeRequired){this.BeginInvoke(new changeText(CalcFinished),t.Result);}else{this.TextBox1.Text=result.ToString();}}上面的做法用到了Control的一个属性InvokeRequired(这个属性是可以在其他线程里访问的),这个属性表明调用是否来自另非UI线程,如果是,则使用BeginInvoke来调用这个函数,否则就直接调用,省去线程封送的过程Invoke,BeginInvoke干什么用的,内部是怎么实现的?这两个方法主要是让给出的方法在控件创建的线程上执行Invoke使用了Win32API的SendMessage,UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);BeginInvoke使用了Win32API的PostMessageUnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);这两个方法向UI线程的消息队列中放入一个消息,当UI线程处理这个消息时,就会在自己的上下文中执行传入的方法,换句话说凡是使用BeginInvoke和Invoke调用的线程都是在UI主线程中执行的,所以如果这些方法里涉及一些静态变量,不用考虑加锁的问题每个线程都有消息队列吗?不是,只有创建了窗体对象的线程才会有消息队列(下面给出<Windows 核心编程>关于这一段的描述)当一个线程第一次被建立时,系统假定线程不会被用于任何与用户相关的任务。