精通C#---多线程,并行,异步编程

// AppDomain ad = Thread.GetDomain();
// Context ctx = Thread.CurrentContext;
public delegate int BinaryOp(int x, int y);

// 内部实现
public sealed class BinaryOp : System.MulticastDelegate
{
	public BinaryOp(object target, uint functionAddress);
	public int Invoke(int x, int y);
	public IAsyncResult BeginInvoke(int x, int y, AsyncCallback cb, object state);
	public int EndInvoke(IAsyncResult result);
}

public interface IAsyncResult
{
	object AsyncState { get; }
	WaitHandle AysncWaitHandle { get; }
	bool CompletedSynchronously { get; }
	bool IsCompleted { get; }
}

// AsyncCallback遵循以下模式
void FunName(IAsyncResult itfAR);

namespace SyncDelegateReview
{
	public delegate int BinaryOp(int x, int y);
	class Program
	{
		static void Main()
		{
			Console.WriteLine("Main() invoked on thread {0}.", Thread.CurrentThread.ManagedThreadId);
			BinaryOp b = new BinaryOp(Add);
			int answer = b(10, 10);
			Console.WriteLine("Doing more work in Main()");
			Console.WriteLine("10 + 10 is {0}.", answer);
			Console.ReadLine();
		}

		static int Add(int x, int y)
		{
			Console.WriteLine("Add() invoked on thread {0}.", Thread.CurrentThread.ManagedThreadId);
			Thread.Sleep(5000);
			return x+y;
		}

		static void Main2()
		{
			BinaryOp b = new BinaryOp(Add);
			IAsyncResult itfAR = b.BeginInvoke(10, 10, null, null);
			Console.WriteLine("Doing more work in main");

			// 直到异步调用完成,此线程才能继续
			int answer = b.EndInvoke(itfAR);
			Console.WriteLine("10 + 10 is {0}", answer);
		}

		// 改进版本
		static void Main3()
		{
			BinaryOp b = new BinaryOp(Add);
			IAsyncResult itfAR = b.BeginInvoke(10, 10, null, null);
			while(!itfAR.IsCompleted)
			{
				Console.WriteLine("Doing more work in Main");
				Thread.Sleep(1000);
			}
			
			int answer = b.EndInvoke(itfAR);
		}

		// 改进版本:次线程在任务完成时主动通知调用线程
	}
}

// 改进版本,次线程完成任务,主调调用 异步开始时的回调函数

namespace AsyncCallbackDelegate
{
	public delegate int BinaryOp(int x, int y);
	class Program
	{
		private static bool isDone = false;
		static void Main()
		{
			Console.WriteLine("Main() invoked on thread {0}", Thread.CurrentThread.ManagedThreadId);
			BinaryOp b = new BinaryOp(Add);
			IAysncResult itfAR = b.BeginInvoke(10, 10, new AsyncCallback(AddComplete), null);

			while(!isDone)
			{
				Thread.Sleep(1000);
				Console.WriteLine("Working...");
			}
			
			Console.ReadLine();
		}

		static int Add(int x, int y)
		{
			//Thread.CurrentThread.ManagedThreadId
			Thread.Sleep(5000);
			return x+y;
		}

		static void AddComplete(IAsyncResult itfAR)
		{
			// Thread.CurrentThread.ManagedThreadId
			Console.WriteLine("Your addition is complete");
			isDone = true;
		}

		// 改进后的AddComplete
		static void AddComplete(IAsyncResult itfAR)
		{
			// Thread.CurrentThread.ManagedThreadId
			Console.WriteLine("Your addition is complete");

			AsyncResult ar = (AsyncResult)itfAR;
			// 获取在另一线程中的触发本线程执行的委托对象
			BinaryOp b = (BinaryOp)ar.AsyncDelegate;
			Console.WriteLine("10+10 is {0}", b.EndInvoke(itfAR));
			isDone = true;
		}
	}
}


// 异步方法调用,携带额外参数版本
static void Main()
{
	...
	IAsyncResult itfAR = b.BeginInvoke(10, 10, new AsyncCallback(AddComplete), "Main thanks you for adding these numbers.");
	...
}

static void AddComplete(IAsyncResult itfAR)
{
	...
	string msg = (string)itfAR.AysncState;
	Console.WriteLine(msg);
	isDone = true;
}

3.System.Threading

Interlocked
Monitor
Mutex
ParameterizedThreadStart
Semaphore
Thread
ThreadPool
ThreadPriority
ThreadStart
ThreadState
Timer
TimerCallback


System.Threading.Thread
CurrentContext
CurrentThread
GetDomain/GetDomainID
Sleep

IsAlive
IsBackground
Name
Priority
ThreadState
Abort
Interrupt
Join
Resume
Start
Suspend

static void Main()
{
	Thread primaryThread = Thread.CurrentThread;
	primaryThread.Name = "ThePrimaryThread";
	// Thread.GetDomain().FriendlyName
	// Thread.CurrentContext.ContextID
	// primaryThread.Name
	// primaryThread.IsAlive
	// primaryThread.Priority
	// primaryThread.ThreadState
}

4.手工创建次线程
创建一个方法作为新线程的入口点
创建一个ParameterizedThreadStart/ThreadStart委托,把上一步所定义方法的地址传给委托的构造函数。
创建一个Thread对象,把ParameterizedThreadStart/ThreadStart委托作为构造函数参数
建立任意初始化线程的特性
调用Thread.Start方法

public class Printer
{
	public void PrintNumbers()
	{
		for(int _i = 0; _i < 10; _i++)
		{
			Thread.Sleep(2000);
		}
	}

	static void Main()
	{
		string threadCount = Console.ReadLine();
		Thread primaryThread = Thread.CurrentThread;
		primaryThread.Name = "Primary";
		// Thread.CurrentThread.Name
		Printer p = new Printer();
		switch(threadCount)
		{
			case "2":
				{
					Thread backgroundThread = new Thread(new ThreadStart(p.PrintNumbers));
					backgroundThread.Name = "Secondary";
					backgroundThread.Start();
				}
				break;

			case "1":
				{
					p.PrintNumbers();
				}
				break;

			default:
				{
					goto case "1";
				}
		}

		MessageBox.Show("xxx");
		Console.ReadLine();
	}
}

////////////参数化版本
class AddParams
{
	public int a, b;
	public AddParams(int numb1, int numb2)
	{
		a = numb1;
		b = numb2;
	}
}

class Program
{
	static void Add(object data)
	{
		if(data is AddParams)
		{
			AddParams ap = (AddParams)data;
			// ap.a + ap.b
		}
	}

	static void Main()
	{
		// Thread.CurrentThread.ManagedThreadId
		AddParams ap = new AddParams(10, 10);
		Thread t = new Thread(new ParameterizedThreadStart(Add));
		t.Start(ap);
		Thread.Sleep(5);
		Console.ReadLine();
	}
}

// 强制等待版本
class Program
{
	private static AutoResetEvent waitHandle = new AutoResetEvent(false);
	static void Main()
	{
		// Thread.CurrentThread.ManagedThreadId
		AddParams ap = new AddParams(10, 10);
		Thread t = new Thread(new ParameterizedThreadStart(Add));
		t.Start(ap);
	
		WaitHandle.WaitOne();
	}

	static void Add(object data)
	{
		if(data is AddParams)
		{
			// ap.a + ap.b
			waitHandle.Set();
		}
	}
}

// 并发问题
public class Printer
{
	public void PrintNumbers()
	{
		for(int _i = 0; _i < 10; _i++)
		{
			Random r = new Random();
			Thread.Sleep(1000 * r.Next(5));
			// _i
		}
	}

	static void Main()
	{
		Printer p = new Printer();
		Thread[] threads = new Thread[10];
		for(int _i = 0; _i < 10; _i++)
		{
			threads[_i] = new Thread(new ThreadStart(p.PrintNumbers));
			threads[_i].Name = string.Format("{0}", _i);
		}

		foreach(Thread t in threads)
		{
			t.Start();
		}
	}
}

// 线程同步 lock
// 试图锁定一个实例级对象私有方法时,用方法本身所在对象的引用即可。
private void SomePrivateMethod()
{
	lock(this)
	{
		//
	}
}

public class Printer
{
	private object threadLock = new object();
	public void PrintNumbers()
	{
		lock(threadLock)
		{
			for(int _i = 0; _i < 10; _i++)
			{
				Thread.Sleep(1000);
				Console.Write("{0}", i);
			}
		}
	}
}

// 线程同步 System.Threading.Monitor
public void PrintNumbers()
{
	Monitor.Enter(threadLock);
	try
	{
		// Thread.CurrentThread.Name
		for(int _i = 0; _i < 10; _i++)
		{
			Random r = new Random();
			Thread.Sleep(1000 * r.Next(5));
			Console.Write("{0}", _i);
		}
	}
	finally
	{
		Monitor.Exit(threadLock);
	}
}

// System.Threading.Interlocked
CompareExchange(ref x1, x2, x3)// if(x1 == x3) x1 = x2
Decrement
Exchange(ref x1, x2)// x1 = x2
Increment

public void AddOne()
{
	lock(myLockToken)
	{
		intVal++;
	}
}

// 改变后
public void AddOne()
{
	int newVal = Interlocked.Increment(ref intVal);
}

// 用[Synchronization]进行同步
// System.Runtime.Remoting.Contexts
// 被修饰类的对象放在同步上下文。使对象的所有实例成员线程安全。会全面降低性能。
// ContextBoundObject及其派生类不能在上下文边界中移动
using System.Runtime.Remoting.Context;
...

[Synchronization]
public class Printer : ContextBoundObject
{
	public void PrintNumbers()
	{
		//
	}
}

// TimerCallback
class Program
{
	static void PrintTime(object state)
	{
		// DateTime.Now.ToLongTimeString
	}
	
	static void Main()
	{
		TimerCallback timeCB = new TimerCallback(PrintTime);
		Timer t = new Timer(
		timeCB, "hello", 0, 1000);
		Console.WriteLine("Hit key to terminate");
	}
}

// 线程池
public static class ThreadPool
{
	...
	public static bool QueueUserWorkItem(WaitCallback callBack);
	public static bool QueueUserWorkItem(WaitCallback callBack, object state);
}

class Program
{
	static void Main()
	{
		Printer p = new Printer();
		WaitCallback workItem = new WaitCallback(PrintTheNumbers);
		for(int _i = 0; _i < 10; _i++)
		{
			ThreadPool.QueueUserWorkItem(workItem, p);
		}
	}

	static void PrintTheNumbers(object state)
	{
		Printer task = (Printer)state;
		task.PrintNumbers();
	}
}

5.System.Threading.Tasks
System.Threading.Tasks.Parallel

using System.Threading.Tasks;
using System.Threading;
using System.IO;

public partial class MainForm : Form
{
	public MainForm()
	{
		InitializeComponent();
	}

	private void btnProcessImages_Click(object sender, EventArgs e)
	{
		ProcessFiles();
	}

	private void ProcessFiles()
	{
		string[] files = Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg", SearchOption.AllDirectories);
		string newDir = @"C:\ModifiedPictures";
		Directory.CreateDirectory(newDir);

		foreach(string currentFile in files)
		{
			string filename = Path.GetFileName(currentFile);
			using(Bitmap bitmap = new Bitmap(currentFile))
			{
				bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
				bitmap.Save(Path.Combine(newDir, filename));
				this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
			}
		}
	}
}

// 改进后版本
Parallel.ForEach(files,
currentFile =>
{
	string filename = Path.GetFileName(currentFile);
	using (Bitmap bitmap = new Bitmap(currentFile))
	{
		bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
		bitmap.Save(Path.Combine(newDir, filename));
	}
})

// 
using (Bitmap bitmap = new Bitmap(currentFile))
{
	bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
	bitmap.Save(Path.Combine(newDir, filename));
	this.Invoke(
	(Action)delegate
	{
		this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
	}
	);
}

//
private void btnProcessImages_Click(object sender, EventArgs e)
{
	Task.Factory.StartNew(
	()=>{ProcessFiles();}
	);
}

// 
public partial class MainForm : Form
{
	private CancellationTokenSource cancelToken = new CancellationTokenSource();
	private void btnCancel_Click(object sender, EventArgs e)
	{
		cancelToken.Cancel();
	}
}

private void ProcessFiles()
{
	ParallelOptions parOpts = new ParallelOptions();
	parOpts.CancellationToken = cancelToken.Token;
	parOpts.MaxDegreeOfParallelism = System.Environment.ProcessorCount;

	string[] files = Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg", SearchOption.AllDirectories);
	string newDir = @"C:\ModifiedPictures";
	Directory.CreateDirectory(newDir);

	try
	{
		Parallel.ForEach(
		files, parOpts, currentFile =>
		{
			parOpts.CancellationToken.ThrowIfCancellationRequested();
			string filename = Path.GetFileName(currentFile);
			using(Bitmap bitmap = new Bitmap(currentFile))
			{
				bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
				bitmap.Save(Path.Combine(newDir, filename));
				this.Invoke(
				(Action)delegate
				{
					this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
				}
				);
			}
		}
		);
	}
	catch(OperationCanceledException ex)
	{
		this.Invoke(
		(Action)delegate
		{
			this.Text = ex.Message;
		}
		);
	}
}

//
private void btnDownload_Click(object sender, EventArgs e)
{
	WebClient wc = new WebClient();
	wc.DownloadStringCompleted += (s, eArgs)=>
	{
		theEBook = eArgs.Result;
		txtBook.Text = theEBook;
	};

	wc.DownloadStringAsync(new Uri("http://www.gutenberg.org/files/98/98-8.txt"));
}

private void btnGetStats_Click(object sender, EventArgs e)
{
	string[] words = theEBook.Split(new char[]{'', '\u000A', ',', '.', ':', '-', '?', '/'}, StringSplitOptions.RemoveEmptyEntries);

	string[] tenMostCommon = FindTenMostCommon(words);
	string longestWord = FindLongestWord(words);
	StringBuilder bookStats = new StringBuilder("Ten Most Common Words are:\n");
	foreach(string s in tenMostCommon)
	{
		bookStats.AppendLine(s);
	}
	
	bookStats.AppendFormat("Longest word is:{0}", longestWord);
	bookStats.AppendLine();
	MessageBox.Show(bookStats.ToString(), "Book info");
}

private string[] FindTenMostCommon(string[] words)
{
	var frequencyOrder = from word in words where word.Length > 6 group word by word into g orderby g.Count() descending select g.Key;
	string[] commonWords = (frequencyOrder.Take(10)).ToArray();
	return commonWords;
}

private string FindLongestWord(string[] words)
{
	return (from w in words orderby w.Length descending select w).FirstOrDefault();
}

6.async 和 await

public partial class MainForm : Form
{
	public MainForm()
	{
		InitializeComponent();
	}

	private void btnCallMethod_Click(object sender, EventArgs e)
	{
		this.Text = DoWork();
	}

	private string DoWork()
	{
		Thread.Sleep(10000);
		return "Done with work!";
	}

	//
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private async void btnCallMethod_Click(object sender, EventArgs e)
		{
			this.Text = await DoWork();
		}

		private Task<string> DoWork()
		{
			return Task.Run(
			()=>
			{
				Thread.Sleep(10000);
				return "Done with work";
			});
		}
	}
}

//
public partial class MainForm : Form
{
	public MainForm()
	{
		InitializeComponent();
	}

	private async void btnCallMethod_Click(object sender, EventArgs e)
	{
		this.Text = await DoWorkAsync();
	}

	private async Task<string> DoWorkAsync()
	{
		return await Task.Run(
		()=>
		{
			Thread.Sleep(10000);
			return "Done with work!";
		}
		);
	}
}

//
private async void btnVoidMethodCall_Click(object sender, EventArgs e)
{
	await MethodReturningVoidAsync();
	MessageBox.Show("Done!");
}

private async Task MethodReturningVoidAsync()
{
	await Task.Run(
	()=>
	{
		Thread.Sleep(4000);
	}
	);
}

//
private async void btnMultiAwaits_Click(object sender, EventArgs e)
{
	// 调用线程挂起,直到await完成。控制返回给方法的调用者。
	await Task.Run(
	()=>
	{
		Thread.Sleep(2000);
	}
	);
	MessageBox.Show("Done with first task!");

	await Task.Run(
	()=>
	{
		Thread.Sleep(2000);
	}
	);
	MessageBox.Show("Done with second task!");

	await Task.Run(
	()=>
	{
		Thread.Sleep(2000);
	}
	);
	MessageBox.Show("Done with third task!");
}

//
class Program
{
	static void Main()
	{
		AddAsync();
		Console.ReadLine();
	}

	private static async Task AddAsync()
	{
		Console.WriteLine("***Adding with Thread objects***");
		Console.WriteLine("Thread Id:{0}", Thread.CurrentThread.ManagedThreadId);
		AddParams ap = new AddParams(10, 10);
		await Sum(app);
		Console.WriteLine("Other thread is done!");
	}

	static async Task Sum(object data)
	{
		await Task.Run(
		()=>
		{
			Console.WriteLine("ID of thread in Add():{0}", Thread.CurrentThread.ManagedThreadId);
			AddParams ap = (AddParams)data;
			Console.WriteLine("{0} + {1} is {2}", ap.a, ap.b, ap.a + ap.b);
		}
		);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值