C#多线程之基础篇2

时间:2023-02-06 15:04:12

  在上一篇C#多线程之基础篇1中,我们主要讲述了如何创建线程、中止线程、线程等待以及终止线程的相关知识,在本篇中我们继续讲述有关线程的一些知识。

五、确定线程的状态

  在这一节中,我们将讲述如何查看一个线程的状态,通常知道一个线程处于什么状态是非常有用的。但是,要注意线程是独立运行的,它的状态可能随时变化。要查看一个线程的状态,我们可以按如下步骤进行:

1、使用Visual Studio 2015创建一个新的控制台应用程序。

2、双击打开“Program.cs”文件,然后修改为如下代码:

 using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread; namespace Recipe05
{
class Program
{
static void DoNothing()
{
Sleep(TimeSpan.FromSeconds());
} static void PrintNumbersWithStatus()
{
WriteLine("Starting...");
WriteLine(CurrentThread.ThreadState.ToString()); for(int i = ; i < ; i++)
{
Sleep(TimeSpan.FromSeconds());
WriteLine(i);
}
} static void Main(string[] args)
{
WriteLine("Starting program..."); Thread t1 = new Thread(PrintNumbersWithStatus);
Thread t2 = new Thread(DoNothing); WriteLine(t1.ThreadState.ToString()); t2.Start();
t1.Start(); for(int i = ; i < ; i++)
{
WriteLine(i.ToString() + " - " + t1.ThreadState.ToString());
} Sleep(TimeSpan.FromSeconds()); t1.Abort(); WriteLine("A thread has been aborted");
WriteLine(t1.ThreadState.ToString());
WriteLine(t2.ThreadState.ToString());
}
}
}

3、运行该控制台应用程序,运行效果(每次运行效果可能不同)如下图所示:

C#多线程之基础篇2

  在上述代码中,我们在“Main”方法中定义了两个不同的线程t1和t2,t1线程在执行过程中被终止,t2线程成功执行完毕。我们可以使用Thread对象的ThreadState属性获得某个线程的状态信息,ThreadState属性是C#枚举类型。

  当程序执行到第34行代码处时,t1线程还没有执行,这个时候t1线程的状态为“ThreadState.Unstarted”。

  当程序执行到第37行代码处时,t1线程开始执行,这个时候该线程的状态为“ThreadState.Running”。

  当运行到第39~42行代码处时,主线程开始执行循环语句,持续打印出29条t1线程的状态,因为在“PrintNumbersWithStatus”方法中调用了“Thread.Sleep”方法,因此在执行主线程的循环的过程中,t1线程的状态在“ThreadState.Running”和“ThreadState.WaitSleepJoin”之间转换。

  当程序执行到第44行代码处时,在主线程中调用了“Thread.Sleep”方法,在等待6秒期间,“PrintNumbersWithStatus”方法中的for循环代码不断执行,因此打印出1、2、3共三行数字。

  当程序执行到第46行代码处时,我们调用了t1的“Abort”方法,从而t1线程被终止。

  当程序执行到第49行代码处时,由于已经在t1线程上调用了“Abort”方法,因此,它的状态为“ThreadState.Aborted”或“ThreadState.AbortRequested”。

  当程序执行到第50行代码处时,因为t2线程正常执行完毕,因此t2线程的状态为“ThreadState.Stopped”。

六、线程优先级

  在这一小节中,我们将讲述线程的优先级,线程的优先级确定了线程所能使用CPU时间的大小。我们按以下步骤来完成线程优先级的学习:

1、使用Visual Studio 2015创建一个新的控制台应用程序。

2、双击打开“Program.cs”文件,修改代码如下所示:

 using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
using static System.Diagnostics.Process; namespace Recipe06
{
class ThreadSample
{
private bool isStopped = false; public void Stop()
{
isStopped = true;
} public void CountNumbers()
{
long counter = ;
while (!isStopped)
{
counter++;
} WriteLine($"{CurrentThread.Name} with {CurrentThread.Priority,10} priority has a count = {counter,15:N0}");
}
} class Program
{
static void RunThreads()
{
var sample = new ThreadSample(); var threadOne = new Thread(sample.CountNumbers);
threadOne.Name = "ThreadOne"; var threadTwo = new Thread(sample.CountNumbers);
threadTwo.Name = "ThreadTwo"; threadOne.Priority = ThreadPriority.Highest;
threadTwo.Priority = ThreadPriority.Lowest; threadOne.Start();
threadTwo.Start(); Sleep(TimeSpan.FromSeconds());
sample.Stop();
} static void Main(string[] args)
{
WriteLine($"Current thread priority: {CurrentThread.Priority}");
WriteLine("Running on all cores available"); RunThreads(); Sleep(TimeSpan.FromSeconds()); WriteLine("Running on a single core");
GetCurrentProcess().ProcessorAffinity = new IntPtr();
RunThreads();
}
}
}

3、运行该控制台应用程序,运行效果(每次运行效果可能不同)如下图所示:

C#多线程之基础篇2

  在上述代码中,我们定义了两个不同的线程threadOne和threadTwo。threadOne线程具有最高的优先级“ThreadPriority.Highest”,threadTwo具有最低的优先级“ThreadPriority.Lowest”。

  在程序执行到第57行代码处,如果我们的计算机是多核计算机,我们将在2秒内获得初始结果,并且具有最高优先级的threadOne线程要比具有最低优先级的threadTwo线程的迭代次数更多一些,但也不会相差太远。但是,如果我们的计算机是单核计算机,则结果大不相同。

  为了模拟单核计算机,我们将ProcessorAffinity的值设置为1,现在这两个线程所迭代的次数将差异非常大,并且程序的执行时间远远大于2秒。这是因为CPU的计算机时间大部分给予了高优先级的线程,而低优先级的线程获得非常少的CPU时间。

七、前台线程和后台线程

  在这一小节中,我们将讲述什么是前台线程和后台线程,并且讲述如何设置这个选项以影响程序的行为。我们按以下步骤来完成前台线程和后台线程的学习:

1、使用Visual Studio 2015创建一个新的控制台应用程序。

2、双击打开“Program.cs”文件,修改代码如下所示:

 using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread; namespace Recipe07
{
class ThreadSample
{
private readonly int iterations; public ThreadSample(int iterations)
{
this.iterations = iterations;
} public void CountNumbers()
{
for(int i = ; i < iterations; i++)
{
Sleep(TimeSpan.FromSeconds(0.5));
WriteLine($"{CurrentThread.Name} prints {i}");
}
}
} class Program
{
static void Main(string[] args)
{
var sampleForeground = new ThreadSample();
var sampleBackground = new ThreadSample(); var threadOne = new Thread(sampleForeground.CountNumbers);
threadOne.Name = "ForegroundThread"; var threadTwo = new Thread(sampleBackground.CountNumbers);
threadTwo.Name = "BackgroundThread";
threadTwo.IsBackground = true; threadOne.Start();
threadTwo.Start();
}
}
}

3、运行该控制台应用程序,运行效果(每次运行效果可能不同)如下图所示:

C#多线程之基础篇2

  在上述代码中,我们定义了两个不同的线程threadOne和threadTwo。当我们创建一个线程时,该线程显示地是一个前台线程,比如threadOne。如果我们要将一个线程设置为后台线程,只需要将该线程的“IsBackground”属性设置为“true”即可,比如threadTwo。我们还配置了两个线程执行的循环次数不一样,threadOne线程所执行的循环次数为10次,threadTwo线程所执行的循环次数为20次,因此threadOne线程要比threadTwo线程早执行完毕。

  从执行结果上来看,当threadOne线程执行完毕后,主程序也结束了,并且后台线程也被终止了,这就是前台线程和后台线程的区别:进程会等待所有的前台进程执行完毕后才结束,单不会等待后台进程执行完毕。

八、向线程传递参数

  在这一小节,我将讲述如何向一个线程传递参数,我们将使用不同的方法来完成这个工作,具体步骤如下所示:

1、使用Visual Studio 2015创建一个新的控制台应用程序。

2、双击打开“Program.cs”文件,修改代码如下所示:

 using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread; namespace Recipe08
{
class ThreadSample
{
private readonly int iterations; public ThreadSample(int iterations)
{
this.iterations = iterations;
} public void CountNumbers()
{
for(int i = ; i <= iterations; i++)
{
Sleep(TimeSpan.FromSeconds(0.5));
WriteLine($"{CurrentThread.Name} prints {i}");
}
}
} class Program
{
static void Count(object iterations)
{
CountNumbers((int)iterations);
} static void CountNumbers(int iterations)
{
for(int i = ; i <= iterations; i++)
{
Sleep(TimeSpan.FromSeconds(0.5));
WriteLine($"{CurrentThread.Name} prints {i}");
}
} static void PrintNumber(int number)
{
WriteLine(number);
} static void Main(string[] args)
{
var sample = new ThreadSample(); var threadOne = new Thread(sample.CountNumbers);
threadOne.Name = "ThreadOne";
threadOne.Start();
threadOne.Join(); WriteLine("--------------------------"); var threadTwo = new Thread(Count);
threadTwo.Name = "ThreadTwo";
threadTwo.Start();
threadTwo.Join(); WriteLine("--------------------------"); var threadThree = new Thread(() => CountNumbers());
threadThree.Name = "ThreadThree";
threadThree.Start();
threadThree.Join(); WriteLine("--------------------------"); int i = ;
var threadFour = new Thread(() => PrintNumber(i)); i = ;
var threadFive = new Thread(() => PrintNumber(i)); threadFour.Start();
threadFive.Start();
}
}
}

3、运行该控制台应用程序,运行效果如下图所示:

C#多线程之基础篇2

  在第50~55行代码处,我们首先创建了一个ThreadSample类型的对象,并将数字10传递给了该类型的构造方法。然后我们将ThreadSample对象的“CountNumbers”方法传递给了线程threadOne的构造方法,“CountNumbers”方法将在线程threadOne中被执行,因此我们通过“CountNumbers”方法将数字10传递给了线程threadOne。

  在第59~62行代码处,我们使用“Thread.Start”的重载方法将一个对象传递给线程threadTwo,要使该段代码正确运行,我们要保证在构造threadTwo线程时,传给给Thread的构造方法的委托要带有一个object类型的参数。在这段代码中,我们将8看作一个对象传递给“Count”方法,该方法有调用了同名的重载方法将object对象转换为整数类型。

  在第66~69行代码处,我们在创建threadThree线程时,给Thread构造方法传递的是一个lambda表达式,该表达式定义了一个不属于任何类的方法,我们在该lambda表达式中调用了“CountNumbers”方法,并将12传递给了“CountNumbers”方法,通过lambda表达式,我们将12传递给了threadThree线程。

  注意:当我们将一个局部变量用于多个lambda表达式时,这些lambda表达式将会共享这个变量的值,在第73~80行代码处,我们将局部变量用于了两个lambda表达式,我们运行threadFour和threadFive线程后,我们发现打印出来的结果都是20。

  未完待续!

C#多线程之基础篇2的更多相关文章

  1. C&num;多线程之基础篇3

    在上一篇C#多线程之基础篇2中,我们主要讲述了确定线程的状态.线程优先级.前台线程和后台线程以及向线程传递参数的知识,在这一篇中我们将讲述如何使用C#的lock关键字锁定线程.使用Monitor锁定线 ...

  2. C&num;多线程之基础篇1

    在多线程这一系列文章中,我们将讲述C#语言中多线程的相关知识,在多线程(基础篇)中我们将学习以下知识点: 创建线程 中止线程 线程等待 终止线程 确定线程的状态 线程优先级 前台线程和后台线程 向线程 ...

  3. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”11之 生产消费者问题

    概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...

  4. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”04之 synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

  5. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”02之 常用的实现多线程的两种方式

    概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...

  6. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”03之 Thread中start&lpar;&rpar;和run&lpar;&rpar;的区别

    概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...

  7. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”05之 线程等待与唤醒

    概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...

  8. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”06之 线程让步

    概要 本章,会对Thread中的线程让步方法yield()进行介绍.涉及到的内容包括:1. yield()介绍2. yield()示例3. yield() 与 wait()的比较 转载请注明出处:ht ...

  9. Java多线程系列--&OpenCurlyDoubleQuote;基础篇”07之 线程休眠

    概要 本章,会对Thread中sleep()方法进行介绍.涉及到的内容包括:1. sleep()介绍2. sleep()示例3. sleep() 与 wait()的比较 转载请注明出处:http:// ...

随机推荐

  1. lcd 图片

    硬件平台:mini2440 软件环境:UCOS2 .ADS1.2 . LCD彩色图片转换工具BMP_to_H工具bmp2h LCD彩色图片转换工具BMP_to_H工具文件夹下的使用说明 在S3C241 ...

  2. POJ3415 Common Substrings

    后缀数组 求长度不小于k的公共子串的个数 代码: #include <stdio.h> #include <string.h> ; int len, len1; int wa[ ...

  3. Web Scale IT 与 6 种 DevOps 工具

    新年伊始,在总结过去一年 IT 行业变化和发展的同时,不少企业更关注未来一年甚至几年的行业趋势.Gartner 于 2014 年发表了文章 Gartner Says By 2017 Web-Scale ...

  4. mpu6050参数获取

    MPU6050其实就是一个 I2C 器件,里面有很多寄存器(但是我们用到的只有几个),我们通过读写寄存器来操作这个芯片.所以首要问题就是 STM32 和 MPU6050 的 I2C 通信.1.配置 S ...

  5. 虹软离线人脸识别 ArcFace 2&period;0 Demo &lbrack;C&plus;&plus;&rsqb;

    环境: win10(10.0.16299.0)+ VS2017 sdk版本:ArcFace v2.0 OPENCV3.43版本 x64平台Debug.Release配置都已通过编译 下载地址:http ...

  6. 高通sdm845&lowbar;la2&period;0源码编译及使用QFIL刷机

    一.下载源码 高通芯片代码下载地址:https://chipcode.qti.qualcomm.com/ . *_amss_standard_oem : 高通私有源码(*为sdm845-la--. * ...

  7. Codeforces 757 C Felicity is Coming&excl;

    题目大意:有n个训练营,m种宠物,每个训练营里里面有gi 个宠物,现在每只宠物都要完成一次进化,种类 相同的宠物进化之后,种类还是相同,种类不同的宠物不能进化成相同种类,且要求所有宠物进化之后,每个 ...

  8. CSS-页面滑屏滚动原理

    现在的网站有的时候为了简洁就是很多的单页滑屏滚动介绍,主要呈现方式有两种,一种是整体的元素一直排列下去,假设有五个需要展示的全屏页面,那么高度是500%,只是展示100%,剩下的可以通过transfo ...

  9. tkinter的GUI设计:界面与逻辑分离(三)-- 多页面

    知识点: 使用 tkinter.Frame.tkraise() 函数去提升当前 tkinter.Frame 的 z 轴顺序,使得多个 tkinter.Frame 的可见性得以切换 本文基于:win7 ...

  10. Nginx设置默认目录

    server { listen ; server_name basic.com; index index.html index.htm index.php; root /www/wwwroot/bas ...