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在这里使用WaitOne就相当于为线程的流动加上了闸门,然后配合Set、Reset就可以控制线程的通断了。一般的场景推荐应用线程池。线程池中的线程使用完后不会被销毁,而是被回收,供下一次使用,这样可以节省反复创建、销毁线程造成的开销。线程池不追求精细化的控制,但能够提供简单的使用多线程的方式,自动进行性能调优,很适合于UI程序中避免程序假死。二、三种异步编程模型三种异步编程模型分别为EAP、APM、TPL,TPL方式使用最简洁。a) EAP(Event-based Asynchronous Pattern)方式使用简单,但不容易实现复杂逻辑,已不推荐使用。EAP使用回调的写法:AutoResetEvent are = new AutoResetEvent(false);
Thread t1 = new Thread(() => { while (true) { Console.WriteLine("waitting open"); are.WaitOne(); Console.WriteLine("Open"); }});
b) APM(Asynchronous Programming Model)方式也不推荐使用了,FileStream还保留有这种写法: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);}
c) TPL(Task Parallel Library)是在.Net4.0之后的新特性,异步实现起来更简洁、直观。比如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); } }}
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