C#多线程技术总结(异步)

简介:

我这里针对现有的C#多线程技术进行一个汇总,一是复习,二是方便索引,文章部份知识点来源于网络,非本人原创。

一、并行(异步):

1.System.Threading.Tasks命名空间下的(TPL):

1.1:Parallel.Invoke --并行执行多个任务,主线程等待并行执行完毕后才开始续续运行。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static  void  Main( string [] args)
{
     Parallel.Invoke( new  ParallelOptions() { MaxDegreeOfParallelism=2},Run1,Run2);
     Console.WriteLine( "我是主线程!" );
     Console.Read();
}
 
static  void  Run1()
{
     Console.WriteLine( "我是任务一,我运行3s" );
     Thread.Sleep(3000);
     Console.WriteLine( "任务一执先完成" );
}
 
static  void  Run2()
{
     Console.WriteLine( "我是任务二,我运行5s" );
     Thread.Sleep(5000);
     Console.WriteLine( "任务二执先完成" );
}

1.2:Parallel.For--循环迭代多个任务,多个任务之间存在并行情况,主线程等待循环迭代的多个任务执行完毕后才开始续续运行。

示例:

1
2
3
4
5
Parallel.For(0, 10, (i) => {
                 Console.WriteLine( "我是第{0}个任务,线程ID是:{1}" ,i,Thread.CurrentThread.ManagedThreadId);
                 Thread.Sleep( new  Random().Next(10) * 10 * 500);
                 Console.WriteLine( "线程ID是:{0}执行完成" , Thread.CurrentThread.ManagedThreadId);
             });

1.3:Parallel.ForEach--循环迭代多个任务,多个任务之间存在并行情况,主线程等待循环迭代的多个任务执行完毕后才开始续续运行。注意它有多个重载方法

示例:

1
2
3
4
5
6
7
8
9
10
11
var  bag =  new  ConcurrentBag< int >();
 
Parallel.ForEach(Partitioner.Create(0, 100), i =>
{
     for  ( int  m = i.Item1; m < i.Item2; m++)
     {
         bag.Add(m);
         Console.WriteLine( "我是第{0}个任务,线程ID是:{1}" , m, Thread.CurrentThread.ManagedThreadId);
     }
});
Console.WriteLine( "并行计算:集合有:{0}" , bag.Count);

1.4:TAP(基于任务的异步编),使用Task类 (注意:默认任务开启后,会在新线程中执行,主线程不会等待任务而是继续下面的执行,若使用Task.WaitAll,则会等待相应的任务完成后才会执行)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//第一种方式启动
var  task1 =  new  Task(() =>  //实例化
             {
                 Run1();
             });
 
task1.Start();  //启动
 
  //第二种方式开启
  var  task2 = Task.Factory.StartNew(() =>  //直接创建任务并启动
             {
                 Run2();
             });
 
//主线程等待任务执行完
  Task.WaitAll(task1, task2);

2.ParallelEnumerable类中的扩展方法(先将枚举对象使用AsParallel转换成ParallelQuery类型,然后就可以使用ParallelQuery在ParallelEnumerable类相关的扩展方法)

示例:

1
2
var  resultList = testList.AsParallel().Where(i=>i>=100).ToList();
  Console.WriteLine( "resultList Count:{0}" , resultList.Count);

3.创建新Thread--新线程启动后,主线程与创建的线程各自执行,若需要主线程等待异步线程执行完成后才执行,则应使用asyncThread.Join方法。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
         static  void  AsyncThreadMethod()
         {
             Console.WriteLine( "我是异步执行线程,线程ID是:{0}" , Thread.CurrentThread.ManagedThreadId);
         }
 
         static  void  AsyncThreadMethod( object  state)
         {
             Console.WriteLine( "我是异步执行线程,线程ID是:{0},状态:{1}" , Thread.CurrentThread.ManagedThreadId,state);
         }
 
 
//创建线程并执行
             Thread asyncThread =  new  Thread( new  ThreadStart(AsyncThreadMethod));
             asyncThread.IsBackground =  true ;
             asyncThread.Start();
 
             Thread asyncThread2 =  new  Thread( new  ParameterizedThreadStart(AsyncThreadMethod));
             asyncThread2.IsBackground =  true ;
             asyncThread2.Start( "这是来自主线程的参数" );

4.使用ThreadPool.QueueUserWorkItem静态方法--WaitCallback回调方法要求其必需带一个object的参数

示例:

1
2
3
ThreadPool.QueueUserWorkItem( new  WaitCallback(AsyncThreadMethod)); //不带参数,则系统将state自动设为null
 
ThreadPool.QueueUserWorkItem( new  WaitCallback(AsyncThreadMethod),  "这是来自主线程的参数" );

5.APM(异步编程模型),利用BeginInvoke与EndInvoke完成异步执行委托方法

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Func< string string > funcDelegate = (s) =>
{
     Console.WriteLine( "我是Func委托方法!" );
     return  "委托方法参数:"  + s;
};
 
//1.无阻塞异步回调
var  aysncResult = funcDelegate.BeginInvoke( "这是来自主线程的参数" new  AsyncCallback((result) =>
{
     //获取委托对象,调用EndInvoke方法获取运行结果
     AsyncResult _result = (AsyncResult)result;
     var  func = (Func< string string >)_result.AsyncDelegate;
     string  data = func.EndInvoke(_result);
     Console.WriteLine(data + ",附加参数:"  + _result.AsyncState.ToString());
}), "其它参数" );
 
//2.阻塞主线程,使主线程等待执行完毕
string  data2 =  null ;
var  aysncResult2 = funcDelegate.BeginInvoke( "这是来自主线程的参数2" null null );
 
data2 = funcDelegate.EndInvoke(aysncResult2); //第一种阻塞方法
 
while  (!aysncResult2.IsCompleted)  //第二种阻塞方法
{
     Thread.Sleep(200);       //虚拟操作
     Console.WriteLine( "主线程等待..." );
}
data2 = funcDelegate.EndInvoke(aysncResult2);
 
WaitHandle[] waitHandles =  new  WaitHandle[]{ aysncResult2.AsyncWaitHandle };
while  (WaitHandle.WaitAll(waitHandles, 5000))  //第三种阻塞方法
{
     Console.WriteLine( "主线程等待..." );
}

6. EAP(基于事件的异步编程)--主要用在客户端应用程序中

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//例子一
var  client =  new  WebClient();
client.DownloadProgressChanged +=  delegate ( object  s, DownloadProgressChangedEventArgs e)
{
     Console.WriteLine( "Download Percent:{0}" , e.ProgressPercentage);
};
client.DownloadStringCompleted +=  delegate ( object  s,DownloadStringCompletedEventArgs e){
     Console.WriteLine( "Download Content Length:{0}" ,e.Result.Length);
     Console.WriteLine( "Download Completed!" );
};
 
client.DownloadStringAsync( new  Uri( "http://www.zuowenjun.cn" ));
 
 
 
//例子二
BackgroundWorker worker =  new  BackgroundWorker();
worker.DoWork += (s, e) => {
     Console.WriteLine( "异步执行中。。。" );
};
worker.RunWorkerCompleted += (s, e) => {
     Console.WriteLine( "异步执行完成。。。" );
};
worker.RunWorkerAsync();

7.async和await关键字

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
     public  Task< double > GetValueAsync( double  num1,  double  num2)
     {
         return  Task.Run(() =>
         {
             for  ( int  i = 0; i < 1000000; i++)
             {
                 num1 = num1 / num2;
             }
             return  num1;
         });
     }
     public  async  void  DisplayValue()
     {
         double  result = await GetValueAsync(1234.5, 1.01); //此处会开新线程处理GetValueAsync任务,然后方法马上返回
         //这之后的所有代码都会被封装成委托,在GetValueAsync任务完成时调用
         System.Diagnostics.Debug.WriteLine( "Value is : "  + result);
     }
 
//调用
DisplayValue(); //不会阻塞主线程

 参考以下相关文章:

C#综合揭秘——细说多线程(上)

C#综合揭秘——细说多线程(下)

8天玩转并行开发系列文章

.NET基础拾遗(5)多线程开发基础

本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/4900468.html  ,如需转载请自行联系原作者

相关文章
|
7天前
|
缓存 监控 算法
基于 C# 网络套接字算法的局域网实时监控技术探究
在数字化办公与网络安全需求增长的背景下,局域网实时监控成为企业管理和安全防护的关键。本文介绍C#网络套接字算法在局域网实时监控中的应用,涵盖套接字创建、绑定监听、连接建立和数据传输等操作,并通过代码示例展示其实现方式。服务端和客户端通过套接字进行屏幕截图等数据的实时传输,保障网络稳定与信息安全。同时,文章探讨了算法的优缺点及优化方向,如异步编程、数据压缩与缓存、错误处理与重传机制,以提升系统性能。
31 2
|
1月前
|
缓存 安全 Java
面试中的难题:线程异步执行后如何共享数据?
本文通过一个面试故事,详细讲解了Java中线程内部开启异步操作后如何安全地共享数据。介绍了异步操作的基本概念及常见实现方式(如CompletableFuture、ExecutorService),并重点探讨了volatile关键字、CountDownLatch和CompletableFuture等工具在线程间数据共享中的应用,帮助读者理解线程安全和内存可见性问题。通过这些方法,可以有效解决多线程环境下的数据共享挑战,提升编程效率和代码健壮性。
64 6
|
2月前
|
Web App开发 Linux C#
C# 网页截图全攻略:三种技术与 Chrome 路径查找指南
本文主要介绍了在 C# 中实现网页截图的几种技术及相关要点。涵盖了 PuppeteerSharp、Selenium 和 HtmlToImage 三种方式,分别阐述了它们的安装步骤及核心代码。同时,针对在 C# 中寻找 Windows 上 chrome.exe 路径这一问题,分析了未安装 Google Chrome 和已安装两种情况下的查找原因,并给出了相关参考链接,还列举了一系列与 C# 使用 Selenium、获取 chrome.exe 路径以及在 Linux 上部署相关的参考资料。
86 11
|
2月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
123 17
|
3月前
|
开发框架 算法 .NET
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
|
3月前
|
开发框架 Cloud Native .NET
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
|
3月前
|
程序员 C# 数据库
C# 比较对象新思路,利用反射技术打造更灵活的比较工具
中途接手的项目,碰到需要在更新对象信息时比较并记录差异的需求,最变态的还有附加要求,怎么办?有没有既能满足需求又能对项目影响最小的方法呢?分享这个我封装的方法,一个利用反射技术打造的更灵活的比较工具
|
4月前
|
人工智能 开发框架 安全
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
|
4月前
|
人工智能 开发框架 前端开发
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
|
4月前
|
C# UED SEO
C# 异步方法async / await任务超时处理
通过使用 `Task.WhenAny`和 `Task.Delay`方法,您可以在C#中有效地实现异步任务的超时处理机制。这种方法允许您在指定时间内等待任务完成,并在任务超时时采取适当的措施,如抛出异常或执行备用操作。希望本文提供的详细解释和代码示例能帮助您在实际项目中更好地处理异步任务超时问题,提升应用程序的可靠性和用户体验。
141 3

相关实验场景

更多