第3章 使用线程池

  • 简介
  • 在线程池中调用委托
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter3.Recipe1
{
	class Program
	{
		static void Main(string[] args)
		{
			int threadId = 0;

			RunOnThreadPool poolDelegate = Test;

			var t = new Thread(() => Test(out threadId));
			t.Start();
			t.Join();

			WriteLine($"Thread id: {threadId}");

			IAsyncResult r = poolDelegate.BeginInvoke(out threadId, Callback, "a delegate asynchronous call");
			r.AsyncWaitHandle.WaitOne();

			string result = poolDelegate.EndInvoke(out threadId, r);
			
			WriteLine($"Thread pool worker thread id: {threadId}");
			WriteLine(result);

			Sleep(TimeSpan.FromSeconds(2));
		}

		private delegate string RunOnThreadPool(out int threadId);

		private static void Callback(IAsyncResult ar)
		{
			WriteLine("Starting a callback...");
			WriteLine($"State passed to a callbak: {ar.AsyncState}");
			WriteLine($"Is thread pool thread: {CurrentThread.IsThreadPoolThread}");
			WriteLine($"Thread pool worker thread id: {CurrentThread.ManagedThreadId}");
		}


		private static string Test(out int threadId)
		{
			WriteLine("Starting...");
			WriteLine($"Is thread pool thread: {CurrentThread.IsThreadPoolThread}");
			Sleep(TimeSpan.FromSeconds(2));
			threadId = CurrentThread.ManagedThreadId;
			return $"Thread pool worker thread id was: {threadId}";
		}
	}
}

  • 向线程池中放入异步操作
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter3.Recipe2
{
	class Program
	{
		static void Main(string[] args)
		{
			const int x = 1;
			const int y = 2;
			const string lambdaState = "lambda state 2";

			ThreadPool.QueueUserWorkItem(AsyncOperation);
			Sleep(TimeSpan.FromSeconds(1));

			ThreadPool.QueueUserWorkItem(AsyncOperation, "async state");
			Sleep(TimeSpan.FromSeconds(1));

			ThreadPool.QueueUserWorkItem( state => 
            {
				WriteLine($"Operation state: {state}");
				WriteLine($"Worker thread id: {CurrentThread.ManagedThreadId}");
				Sleep(TimeSpan.FromSeconds(2));
			}, "lambda state");

			ThreadPool.QueueUserWorkItem( _ =>
			{
				WriteLine($"Operation state: {x + y}, {lambdaState}");
				WriteLine($"Worker thread id: {CurrentThread.ManagedThreadId}");
				Sleep(TimeSpan.FromSeconds(2));
			}, "lambda state");

			Sleep(TimeSpan.FromSeconds(2));
		}

		private static void AsyncOperation(object state)
		{
			WriteLine($"Operation state: {state ?? "(null)"}");
			WriteLine($"Worker thread id: {CurrentThread.ManagedThreadId}");
			Sleep(TimeSpan.FromSeconds(2));
		}
	}
}

  • 线程池与并行度
using System;
using System.Diagnostics;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter3.Recipe3
{
	class Program
	{
		static void Main(string[] args)
		{
			const int numberOfOperations = 500;
			var sw = new Stopwatch();
			sw.Start();
			UseThreads(numberOfOperations);
			sw.Stop();
			WriteLine($"Execution time using threads: {sw.ElapsedMilliseconds}");

			sw.Reset();
			sw.Start();
			UseThreadPool(numberOfOperations);
			sw.Stop();
			WriteLine($"Execution time using the thread pool: {sw.ElapsedMilliseconds}");
		}

		static void UseThreads(int numberOfOperations)
		{
			using (var countdown = new CountdownEvent(numberOfOperations))
			{
				WriteLine("Scheduling work by creating threads");
				for (int i = 0; i < numberOfOperations; i++)
				{
					var thread = new Thread(() =>
                    {
						Write($"{CurrentThread.ManagedThreadId},");
						Sleep(TimeSpan.FromSeconds(0.1));
						countdown.Signal();
					});
					thread.Start();
				}
				countdown.Wait();
				WriteLine();
			}
		}

		static void UseThreadPool(int numberOfOperations)
		{
			using (var countdown = new CountdownEvent(numberOfOperations))
			{
				WriteLine("Starting work on a threadpool");
				for (int i = 0; i < numberOfOperations; i++)
				{
					ThreadPool.QueueUserWorkItem( _ => 
                    {
						Write($"{CurrentThread.ManagedThreadId},");
						Sleep(TimeSpan.FromSeconds(0.1));
						countdown.Signal();
					});
				}
				countdown.Wait();
				WriteLine();
			}
		}
	}
}

  • 实现一个取消选项
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter3.Recipe4
{
	class Program
	{
		static void Main(string[] args)
		{
			using (var cts = new CancellationTokenSource())
			{
				CancellationToken token = cts.Token;
				ThreadPool.QueueUserWorkItem(_ => AsyncOperation1(token));
				Sleep(TimeSpan.FromSeconds(2));
				cts.Cancel();
			}

			using (var cts = new CancellationTokenSource())
			{
				CancellationToken token = cts.Token;
				ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token));
				Sleep(TimeSpan.FromSeconds(2));
				cts.Cancel();
			}

			using (var cts = new CancellationTokenSource())
			{
				CancellationToken token = cts.Token;
				ThreadPool.QueueUserWorkItem(_ => AsyncOperation3(token));
				Sleep(TimeSpan.FromSeconds(2));
				cts.Cancel();
			}

			Sleep(TimeSpan.FromSeconds(2));
		}

		static void AsyncOperation1(CancellationToken token)
		{
			WriteLine("Starting the first task");
			for (int i = 0; i < 5; i++)
			{
				if (token.IsCancellationRequested)
				{
					WriteLine("The first task has been canceled.");
					return;
				}
				Sleep(TimeSpan.FromSeconds(1));
			}
			WriteLine("The first task has completed succesfully");
		}

		static void AsyncOperation2(CancellationToken token)
		{
			try
			{
				WriteLine("Starting the second task");

				for (int i = 0; i < 5; i++)
				{
					token.ThrowIfCancellationRequested();
					Sleep(TimeSpan.FromSeconds(1));
				}
				WriteLine("The second task has completed succesfully");
			}
			catch (OperationCanceledException)
			{
				WriteLine("The second task has been canceled.");
			}
		}

		static void AsyncOperation3(CancellationToken token)
		{
			bool cancellationFlag = false;
			token.Register(() => cancellationFlag = true);
			WriteLine("Starting the third task");
			for (int i = 0; i < 5; i++)
			{
				if (cancellationFlag)
				{
					WriteLine("The third task has been canceled.");
					return;
				}
				Sleep(TimeSpan.FromSeconds(1));
			}
			WriteLine("The third task has completed succesfully");
		}
	}
}

  • 在线程池中使用等待事件处理器及超时
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;


namespace Chapter3.Recipe5
{
	class Program
	{
		static void Main(string[] args)
		{
			RunOperations(TimeSpan.FromSeconds(5));
			RunOperations(TimeSpan.FromSeconds(7));
		}

		static void RunOperations(TimeSpan workerOperationTimeout)
		{
			using (var evt = new ManualResetEvent(false))
			using (var cts = new CancellationTokenSource())
			{
				WriteLine("Registering timeout operation...");
				var worker = ThreadPool.RegisterWaitForSingleObject(evt
                    , (state, isTimedOut) => WorkerOperationWait(cts, isTimedOut)
                    , null
                    , workerOperationTimeout
                    , true);

				WriteLine("Starting long running operation...");
				ThreadPool.QueueUserWorkItem(_ => WorkerOperation(cts.Token, evt));

				Sleep(workerOperationTimeout.Add(TimeSpan.FromSeconds(2)));
				worker.Unregister(evt);
			}
		}

		static void WorkerOperation(CancellationToken token, ManualResetEvent evt)
		{
			for(int i = 0; i < 6; i++)
			{
				if (token.IsCancellationRequested)
				{
					return;
				}
				Sleep(TimeSpan.FromSeconds(1));
			}
			evt.Set();
		}

		static void WorkerOperationWait(CancellationTokenSource cts, bool isTimedOut)
		{
			if (isTimedOut)
			{
				cts.Cancel();
				WriteLine("Worker operation timed out and was canceled.");
			}
			else
			{
				WriteLine("Worker operation succeded.");
			}
		}
	}
}

  • 使用计时器
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter3.Recipe6
{
	class Program
	{
		static void Main(string[] args)
		{
			WriteLine("Press 'Enter' to stop the timer...");
			DateTime start = DateTime.Now;
			_timer = new Timer(_ => TimerOperation(start), null
                , TimeSpan.FromSeconds(1)
                , TimeSpan.FromSeconds(2));
		    try
		    {
		        Sleep(TimeSpan.FromSeconds(6));

		        _timer.Change(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(4));

		        ReadLine();
		    }
		    finally
		    {
		        _timer.Dispose();
		    }
		}

		static Timer _timer;

		static void TimerOperation(DateTime start)
		{
			TimeSpan elapsed = DateTime.Now - start;
			WriteLine($"{elapsed.Seconds} seconds from {start}. " +
			          $"Timer thread pool thread id: {CurrentThread.ManagedThreadId}");
		}
	}
}

  • 使用BackgroundWorker组件
using System;
using System.ComponentModel;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter3.Recipe7
{
	class Program
	{
		static void Main(string[] args)
		{
			var bw = new BackgroundWorker();
			bw.WorkerReportsProgress = true;
			bw.WorkerSupportsCancellation = true;

			bw.DoWork += Worker_DoWork;
			bw.ProgressChanged += Worker_ProgressChanged;
			bw.RunWorkerCompleted += Worker_Completed;

			bw.RunWorkerAsync();

			WriteLine("Press C to cancel work");
			do
			{
				if (ReadKey(true).KeyChar == 'C')
				{
					bw.CancelAsync();
				}
				
			}
			while(bw.IsBusy);
		}

		static void Worker_DoWork(object sender, DoWorkEventArgs e)
		{
			WriteLine($"DoWork thread pool thread id: {CurrentThread.ManagedThreadId}");
			var bw = (BackgroundWorker) sender;
			for (int i = 1; i <= 100; i++)
			{
				if (bw.CancellationPending)
				{
					e.Cancel = true;
					return;
				}
				if (i%10 == 0)
				{
					bw.ReportProgress(i);
				}

				Sleep(TimeSpan.FromSeconds(0.1));
			}

			e.Result = 42;
		}

		static void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			WriteLine($"{e.ProgressPercentage}% completed. " +
			          $"Progress thread pool thread id: {CurrentThread.ManagedThreadId}");
		}

		static void Worker_Completed(object sender, RunWorkerCompletedEventArgs e)
		{
			WriteLine($"Completed thread pool thread id: {CurrentThread.ManagedThreadId}");
			if (e.Error != null)
			{
				WriteLine($"Exception {e.Error.Message} has occured.");
			}
			else if (e.Cancelled)
			{
				WriteLine($"Operation has been canceled.");
			}
			else
			{
				WriteLine($"The answer is: {e.Result}");
			}
		}
	}
}

posted on 2019-05-14 17:06  威武的祥哥  阅读(112)  评论(0)    收藏  举报

导航