1、在C#中使用多线程可以使用Thread

代码例子:

 public class ThreadExample
{
public static void ThreadProc()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
}
}
public static void Start()
{
Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();
for (int i = 0; i < 4; i++)
{
Console.WriteLine("主线程开始工作.");
}
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
t.Join();
Console.WriteLine("工作结束");
Console.ReadLine();
}
} internal class Program
{
static void Main(string[] args)
{
ThreadExample.Start();
}
}

由于我们写了 t.Join(); 所以,工作结束一定是最后一步进行的,但是。在Start方法中主线程和副线程是交替打印的,那么如何控制线程的进行呢?

有多种方法

在这之前,我先写一个例子,你们猜猜打印出来的结果是多少?

 public class Sample1
{
public static void Show()
{
for (int i = 0; i < 5; i++)
{
new Thread(AddOne).Start();
}
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine("sum = " + sum);
Console.ReadKey();
}
private static int sum = 0;
public static void AddOne()
{
for (int i = 0; i < 100_0000; i++)
{
sum += 1;
}
}
}

可以看出来我将1000000累加了5次,但是结果不是5000000,原因就是在累加过程中,sum是交替执行的

所以,在这种情况下,我们必须使用同步锁,

public class Sample2
{
public static void Show()
{
object obj= new object(); //使用锁对象进行线程同步
for (int i = 0; i < 5; i++)
{
new Thread(()=>AddOne(obj)).Start();
}
Thread.Sleep(TimeSpan.FromSeconds(5));
lock (obj)
{
Console.WriteLine("sum = " + sum);
}
Console.ReadKey();
}
private static volatile int sum = 0;
public static void AddOne(object obj)
{
for (int i = 0; i < 100_0000; i++)
{
lock (obj)
{
sum += 1;
}
}
}
}

这样结果就是5000000了,但是正常开发中,我们一般用Task,很少用到Thread了,(代表我自己)

我们继续修改代码

 public class TaskSample1
{
public static void Show()
{
var task=Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
}
});
task.Wait();
for (int i = 0; i < 100; i++)
{
Console.WriteLine("主线程: 执行方法。");
}
Console.WriteLine("主线程:ThreadProc。加入已恢复。按“Enter”结束程序。");
Console.ReadLine();
}
}

但是如果我们的Task很多呢 需要 Task.WaitAll(tasks);

 public class TaskSample2
{
public static void Show()
{ Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Task.Run(() => Thread.Sleep(2000));
}
try
{
Task.WaitAll(tasks);
}
catch (AggregateException ae)
{
Console.WriteLine("One or more exceptions occurred: ");
foreach (var ex in ae.Flatten().InnerExceptions)
Console.WriteLine(" {0}", ex.Message);
} Console.WriteLine("Status of completed tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
Console.WriteLine("主线程:ThreadProc。加入已恢复。按“Enter”结束程序。");
Console.ReadLine();
}
}

现在我们已经学会基础的线程控制了,

但是一个任务的进行,会遇到很多的问题,不是你简单的写两个任务,这两个任务就会按照你的想法去执行下去

比如,

1、在执行下载任务的时候没电了,

2、在执行下载任务的时候想取消了

这个时候,你该怎么做呢

看代码:

public class Sample4
{
public static void Show()
{
CancellationTokenSource cts = new CancellationTokenSource();
// 可以直接设置10秒后任务停止 CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
cts.Token.Register(() => { Console.WriteLine("任务已停止"); });
Task.Run(() =>
{
int i = 0;
while (!cts.IsCancellationRequested)
{
i++;
Console.WriteLine(i);
Task.Delay(1000).Wait();
}
});
// cts.CancelAfter(5000); //5秒后取消操作 也可以使用Cannel直接取消
//这个可以用在你下载文件,或者读取文件出错的时候使用 //也可以设置按下ESC键时任务停止
var key = Console.ReadKey();
if (key.Key == ConsoleKey.Escape)
{
cts.Cancel();
}
Console.ReadLine();
}
}

这段代码中,你每隔一秒累加1,功能就是按下ESC键,停止累加操作,结束程序

CancellationTokenSource你把它当作一个回调函数,

可以在任务进行的时候取消任务,

在C#中About()方法已经过期了,现在大多数都用CancellationTokenSource来代替。

我在上面写过, object obj= new object(); //使用锁对象进行线程同步

我们要同步线程的时候用到。

但是在大型项目中,我们还是用AutoResetEvent锁和ManualResetEvent锁,我在下期再讲

C#中多线程的用法的更多相关文章

  1. qt中多线程用法总结

    1.多线程的理解 在操作系统中线程和进程划分. 操作系统可以同时执行多个任务,每个任务就是进程:进程可以同时执行多个任务,每个任务就是线程. 线程之间相互独立,抢占式执行.对于单核CPU来说同一时刻只 ...

  2. 通过编写聊天程序来熟悉python中多线程及socket的用法

    1.引言 Python中提供了丰富的开源库,方便开发者快速就搭建好自己所需要的应用程序.本文通过编写基于tcp/ip协议的通信程序来熟悉python中socket以及多线程的使用. 2.python中 ...

  3. Java 中 synchronized的用法详解(四种用法)

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.本文给大家介绍java中 synchronized的用法,对本文感兴趣的朋友一起看看吧 ...

  4. Python爬虫进阶五之多线程的用法

    前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...

  5. java成神之——java中string的用法

    java中String的用法 String基本用法 String分割 String拼接 String截取 String换行符和format格式化 String反转字符串和去除空白字符 String获取 ...

  6. java中stringBuilder的用法

    java中stringBuilder的用法 String对象是不可改变的.每次使用 System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间.在需 ...

  7. Delphi 中多线程同步的一些处理方法

    Delphi 中多线程同步的一些处理方法   当创建了多个线程,并且多个线程都要访问同一资源,,就有可能出现混乱,于是用Synchronize来控制,使同一时间只有一个线程使用那部分资源,Synchr ...

  8. [转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法

    一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBo ...

  9. C#中string.format用法详解

    C#中string.format用法详解 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Form ...

  10. SQL中distinct的用法

    SQL中distinct的用法   1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...

随机推荐

  1. 2022-11-04:给定一个正数n,表示有多少个节点 给定一个二维数组edges,表示所有无向边 edges[i] = {a, b} 表示a到b有一条无向边 edges一定表示的是一个无环无向图,也

    2022-11-04:给定一个正数n,表示有多少个节点 给定一个二维数组edges,表示所有无向边 edges[i] = {a, b} 表示a到b有一条无向边 edges一定表示的是一个无环无向图,也 ...

  2. 2021-12-01:给定一个正数数组arr,代表每个人的体重。给定一个正数limit代表船的载重,所有船都是同样的载重量。 每个人的体重都一定不大于船的载重。 要求: 1, 可以1个人单独一搜船;

    2021-12-01:给定一个正数数组arr,代表每个人的体重.给定一个正数limit代表船的载重,所有船都是同样的载重量. 每个人的体重都一定不大于船的载重. 要求: 1, 可以1个人单独一搜船: ...

  3. < Python全景系列-2 > Python数据类型大盘点

    <Python全景系列-2> Python数据类型大盘点 欢迎来到我们的系列博客<Python全景系列>!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高 ...

  4. 码云SSH公钥及仓库建设

    码云SSH公钥及仓库建设 第一步注册码云账号并按图示点击 在新打开的界面,按图示点击 进入点击如下图步骤 然后照着做下图 ssh-keygen -t rsa -C "xxxxx@xxxxx. ...

  5. MongoDB + SpringBoot 的基础CRUD、聚合查询

    1.数据准备 1.1.springboot导包 springboot版本:2.7.10 点击查看代码 <!--mongodb的包--> <dependency> <gro ...

  6. AcWing 3729. 改变数组元素

    给定一个空数组 V 和一个整数数组 a1,a2,-,an. 现在要对数组 V进行 n次操作. 第 i次操作的具体流程如下: 从数组 V尾部插入整数 0.    2.将位于数组 V末尾的 ai 个元素都 ...

  7. linux DHCP

    目录 一.DHCP概念 二.DHCP工作过程 三.DHCP实验 一.DHCP概念 概念:动态主机配置协议,自动为计算机分配tcp/ip参数 DHCP的优点:1.减少管理员的工作难度 2.避免错误的可能 ...

  8. 前端开发如何更好的避免样式冲突?级联层(CSS@layer)

    作者:vivo 互联网前端团队 - Zhang Jiqi 本文主要讲述了CSS中的级联层(CSS@layer),讨论了级联以及级联层的创建.嵌套.排序和浏览器支持情况.级联层可以用于避免样式冲突,提高 ...

  9. springboot接入influxdb

    转载请注明出处: 1.添加maven依赖 <dependency> <groupId>org.springframework.boot</groupId> < ...

  10. 预测 motif 的计算原理

    本文章来源于简书,作者小潤澤,已获原作者授权:部分内容有调整. 前言 蛋白质中功能的基本单元是 domain,是一种特殊的三维结构,不同结构的 domain 与其他分子特异性结合从而发挥功能.与此类似 ...