博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
了解一些多线程相关的知识
阅读量:4596 次
发布时间:2019-06-09

本文共 3569 字,大约阅读时间需要 11 分钟。

一、基础知识
a)多线程的基础类为Thread,实际应用中一般用线程池,而不会直接用到Thread类。Thread基本的使用为:

int i = 5;

Thread thread = new Thread((p) => {
  Console.WriteLine(p);
});
thread.Start(i);

可以用lambda写法,也可以指向一个方法,参数通过Start(i)来传递。

b) 线程间的同步有几种方法
可以在一个方法加上[MethodImpl(MethodImplOptions.Synchronized)],这样这个方法就无法被多个线程同时访问了,这属于方法粒度的控制。
lock和Monitor可以提供代码块粒度的控制,用lock(<locker>){}或Monitor.Enter(<locker>)\Monitor.Exit(<locker>)包围的代码块可以做到只允许一个线程同时访问。
c) 对于单例模式,如果要保证线程安全,最好用这样的写法:

class Singleton {

  private Singleton() { }
  private static object locker = new object();
  private static Singleton instance = null;
  public static Singleton GetSingleton() {
    if (instance == null) {
      lock (locker) {
        instance = new Singleton();
      }
    }
    return instance;
  }
}

需要注意的是,只有在instance==null的时候,才进行lock并初始化。

d)线程的控制和线程池
除了锁之外,还可以通过ManualResetEvent、AutoResetEvent来进行线程间的的通讯,以进行更精细的控制。基本的方法为WaitOne、Set、Reset

AutoResetEvent are = new AutoResetEvent(false);

Thread t1 = new Thread(() => {
  while (true) {
    Console.WriteLine("waitting open");
    are.WaitOne();
    Console.WriteLine("Open");
  }
});

在这里使用WaitOne就相当于为线程的流动加上了闸门,然后配合Set、Reset就可以控制线程的通断了。
一般的场景推荐应用线程池。线程池中的线程使用完后不会被销毁,而是被回收,供下一次使用,这样可以节省反复创建、销毁线程造成的开销。线程池不追求精细化的控制,但能够提供简单的使用多线程的方式,自动进行性能调优,很适合于UI程序中避免程序假死。
二、三种异步编程模型
三种异步编程模型分别为EAP、APM、TPL,TPL方式使用最简洁。
a) EAP(Event-based Asynchronous Pattern)方式使用简单,但不容易实现复杂逻辑,已不推荐使用。EAP使用回调的写法:

private static void EAP() {

  WebClient wc = new WebClient();
  wc.DownloadStringCompleted += Wc_DownloadStringCompleted;
  wc.DownloadStringAsync(new Uri("http://www.github.com"));
  Console.WriteLine("Downloading");
}
private static void Wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) {
  Console.WriteLine(e.Result);
}

b) APM(Asynchronous Programming Model)方式也不推荐使用了,FileStream还保留有这种写法:

private static void APM() {

  string filePath = "e:EFCore.txt";
  using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) {
    var buffer = new byte[128];
    var asyncState = new AsyncState { FS = fileStream, Buffer = buffer, EvtHandle = new ManualResetEvent(false) };
    IAsyncResult asyncResult = fileStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(AsyncReadCallBack), asyncState);
    asyncState.EvtHandle.WaitOne();
    Console.WriteLine();
    Console.WriteLine("read complete");
    Console.ReadKey();
  }
}
public static void AsyncReadCallBack(IAsyncResult asyncResult) {
  var asyncState = (AsyncState)asyncResult.AsyncState;
  int readCn = asyncState.FS.EndRead(asyncResult);
  if (readCn > 0) {
    byte[] buffer;
    if (readCn == 128) {
      buffer = asyncState.Buffer;
    }
    else {
      buffer = new byte[readCn];
      Array.Copy(asyncState.Buffer, 0, buffer, 0, readCn);
    }
    string readContent = Encoding.UTF8.GetString(buffer);
    Console.Write(readContent);
    if (readCn < 128) {
      asyncState.EvtHandle.Set();
    }
    else {
      Array.Clear(asyncState.Buffer, 0, 128);
      asyncState.FS.BeginRead(asyncState.Buffer, 0, 128, new AsyncCallback(AsyncReadCallBack), asyncState);
    }
  }
}

c) TPL(Task Parallel Library)是在.Net4.0之后的新特性,异步实现起来更简洁、直观。比如FileStream的使用:

async static void TPL() {

  string filePath = "e:/文章汇总/083.20170906 .Net Core(二)EFCore.txt";
  using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) {
    var buffer = new byte[128];
    var readLength = 0;
    while ((readLength = await fileStream.ReadAsync(buffer, 0, buffer.Length)) != 0) {
      string content = Encoding.UTF8.GetString(buffer);
      Console.WriteLine(content);
    }
    Console.WriteLine("complete");
  }
}

方法要被被async修饰,同时fileStream前使用await,然后就可以用很自然的的编码方式了。WinForm中的事件处理方法、MVC中的Action都可以使用这种方法。

学习资料:如鹏网.net提高班http://www.rupeng.com/News/10/4603.shtml

转载于:https://www.cnblogs.com/zhixin9001/p/7545545.html

你可能感兴趣的文章
hihocoder1323 回文字符串
查看>>
MD5加密
查看>>
搜索评价指标——NDCG
查看>>
浅复制与深复制
查看>>
codeReview
查看>>
内存泄漏 tensorflow
查看>>
javascript 体验倒计时:距离国庆还有多长时间
查看>>
centos 7 修改ssh登录端口
查看>>
wraps
查看>>
11、深入理解计算机系统笔记:存储器层次结构,利用局部性
查看>>
小白整理一下PHP常用字符串函数
查看>>
一千行mysql笔记
查看>>
排查Java高CPU占用原因
查看>>
[iOS]数据库第三方框架FMDB详细讲解
查看>>
让IE6/IE7/IE8浏览器支持CSS3属性
查看>>
Windows 某些软件显示"口口"解决办法
查看>>
PHP+Hadoop+Hive+Thrift+Mysql实现数据统计分析
查看>>
和同事下班路上讨论心得(服务器部署的几点问题)
查看>>
Spring学习总结五——SpringIOC容器五
查看>>
解决多个ajax页面请求,页面loading阻塞问题
查看>>