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-04-09:给你两个长度分别 n 和 m 的整数数组 nums 和 multipliers ,其中 n >= m , 数组下标 从 1 开始 计数。 初始时,你的分数为 0 。 你需要执行恰

    2022-04-09:给你两个长度分别 n 和 m 的整数数组 nums 和 multipliers ,其中 n >= m , 数组下标 从 1 开始 计数. 初始时,你的分数为 0 . 你需要 ...

  2. docker安装kibana,报错Kibana server is not ready yet,未解决

    1.命令 docker run -d -e ELASTICSEARCH_URL=http://192.168.101.158:9200 -p 5601:5601 --name kibana kiban ...

  3. Django接入SwaggerAPI接口文档-完整操作(包含错误处理)

    Swagger的简介: Swagger是一个规范和完整的框架,用于生成.描述.调用和可视化RESTful风格的Web服务,在做后端开发的同时自动生成一个API文档供前端查看,当接口有变动时,对应的接口 ...

  4. vue全家桶进阶之路49:Vue3 环境变量

    vue3 环境变量 在Vue3中,可以通过环境变量来管理应用程序中的配置.这些配置可以包括后端API的URL.API key.跟踪ID等等.在不同的开发.测试.生产环境中使用不同的配置是非常有用的.V ...

  5. 警惕看不见的重试机制:为什么使用RPC必须考虑幂等性

    0 文章概述 在RPC场景中因为重试或者没有实现幂等机制而导致的重复数据问题,必须引起大家重视,有可能会造成例如一次购买创建多笔订单,一条通知信息被发送多次等问题,这是技术人员必须面对和解决的问题. ...

  6. SpringBoot整合OSS文件上传

    一.注册阿里云账号并开通OSS服务 1.登录阿里云账号 2.创建一个bucket 3.创建子用户 对自用户分配权限,打开操作OSS的全部权限(也可根据业务需求进行更改) 4.配置上传跨域规则 任何来源 ...

  7. 【VS Code 与 Qt6】QCheckBox的图标为什么不会切换?

    本篇专门扯一下有关 QCheckBox 组件的一个问题.老周不水字数,直接上程序,你看了就明白. #include <QApplication> #include <QWidget& ...

  8. Kubernetes(k8s)包管理工具Helm:Helm包管理

    目录 一.系统环境 二.前言 三.包管理工具Helm简介 四.安装部署helm 五.配置helm以及helm常用命令 六.使用helm安装应用 七.搭建helm私有仓库 八.总结 一.系统环境 本文主 ...

  9. 手撕HashMap(一)

    HashMap基本了解 1. jdk1.7之前,HashMap底层只是数组和链表 2. jdk1.8之后,HashMap底层数据结构当链表长度超过8时,会转为红黑树 3. HashMap利用空间换时间 ...

  10. Dlang 并行化

    Dlang 并行化 好难受,dlang 生态太差,没办法,学了半天才明白. 我尽量以精炼的语言解释. 采用 定义,例子(代码),解释 的步骤讲解. 所以你可能看到很多代码,一点解释-- 我会省略一些 ...