Recently I read the book "C#Advanced Programming" again. I want to make a note of the knowledge points in the chapter "Tasks, Threads and Synchronization", so that I can forget that a knowledge point can be used directly in future work. Here is a summary.
Parallel Data and Tasks Parallel
1. Parallel.For
1. Run iteration in parallel with Parallel.For
static void ParallelFor() { ParallelLoopResult result = Parallel.For(0, 10, item => { Console.WriteLine("{0},task{1},thread{2}", item, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); }); Console.WriteLine("Complete:{0}", result.IsCompleted); }
2. Stop the For cycle early by using ParallelLoopState's Break() method
static void ParallelForBreak() { ParallelLoopResult result = Parallel.For(0, 10, (item, pls) => { Console.WriteLine("{0},task{1},thread{2}", item, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); if (item > 5) pls.Break(); }); Console.WriteLine("Complete:{0}", result.IsCompleted); Console.WriteLine("Ignore:{0}", result.LowestBreakIteration); }
3. Initialize each thread
static void ParallelForInit() { ParallelLoopResult result = Parallel.For<string>(0, 20, () => //Func<TLocal>Call once for each thread used to perform iteration { Console.WriteLine("Initialize, Task:{0},Threads:{1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); return string.Format("Threads:{0}", Thread.CurrentThread.ManagedThreadId); }, (item, pls, str1) => //Func<long, ParallelLoopState, TLocal, TLocal> Delegates defined for the loop body //The first parameter is the loop iteration, the second parameter ParallelLoopState Allow stop loop //The third parameter receives the value returned by the initialization task, and the type is generic For Parameter Defined { Console.WriteLine("In execution, number:{0},str1: {1},Tasks:{2},Threads:{3}", item, str1, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); return string.Format("Number:{0}", item); }, (str1) => //Action<TLocal> This method is called only once per thread, this is a thread exit method { Console.WriteLine("Complete:{0}", str1); }); }
4. Cancel Tasks
/// <summary> /// Cancel Task /// </summary> static void ParallelCancel() { CancellationTokenSource cts = new CancellationTokenSource(); //Register a delegation when a task is cancelled cts.Token.Register(() => { Console.WriteLine("Task cancelled"); }); try { ParallelLoopResult result = Parallel.For(0, 10, new ParallelOptions() { CancellationToken = cts.Token }, item => { Console.WriteLine("Cycle:{0}", item); Thread.Sleep(1000); if (item == 5) cts.Cancel(); }); } catch (OperationCanceledException ex) { Console.WriteLine(ex.Message); } }
2. Parallel.ForEach
1. Traverse asynchronously with Parallel.ForEach
static void ParallelForeach() { string[] data = { "Zhang San", "Li Si", "King Five", "Zhao Six", "Qian Qi" }; ParallelLoopResult result = Parallel.ForEach(data, item => { Console.WriteLine("Value:{0},Tasks:{1},Threads:{2}", item, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); }); }
2. Break() method of ParallelLoopState to interrupt ForEach traversal
static void ParallelForeachBreak() { string[] data = { "Zhang San", "Li Si", "King Five", "Zhao Six", "Qian Qi" }; ParallelLoopResult result = Parallel.ForEach(data, (item, pls, index) => { Console.WriteLine("Value:{0},Indexes:{1},Tasks:{2},Threads:{3}", item, index, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); if (item == "King Five") pls.Break(); }); }
3. Parallel.Invoke
1. Call multiple methods through the Parallel.Invoke() method. If multiple tasks should run in parallel, you can use the Parallel.Invoke method, which provides a task parallelism mode
static void ParallelInvoke() { Parallel.Invoke(Zhangsan, Lisi); } static void Zhangsan() { Console.WriteLine("Zhang San"); } static void Lisi() { Console.WriteLine("Li Si"); }
Task Task Task
1. Create a method for task execution.
static object taskMethodLock = new object(); static void TaskMethod(object title) { lock (taskMethodLock) { Console.WriteLine(title); Console.WriteLine("Tasks:{0},Threads:{1}", Task.CurrentId == null ? -1 : Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Thread pool:{0}", Thread.CurrentThread.IsThreadPoolThread); Console.WriteLine("Background threads:{0}", Thread.CurrentThread.IsBackground); Console.WriteLine(); } }
2. Creating tasks in different ways
/// <summary> /// Create tasks in different ways /// </summary> static void CreateTask() { //Mode 1: Use instantiated TaskFactory class TaskFactory tf = new TaskFactory(); Task task = tf.StartNew(TaskMethod, "Use TaskFactory Class Start Task"); //Mode 2: Use Task Static Properties of Classes Factory Task.Factory.StartNew(TaskMethod, "Use Task Static Properties of Classes Factory Start Task"); //Mode 3: Use Task Constructor of class Task task1 = new Task(TaskMethod, "Use Task Class Constructor Start Task"); task1.Start(); }
3. Creating synchronization tasks
/// <summary> /// Synchronize Tasks /// </summary> static void SyncTask() { TaskMethod("Main Thread"); Task task = new Task(TaskMethod, "Synchronize Tasks"); task.RunSynchronously(); }
4. Create long-running tasks
/// <summary> /// Create long-running tasks /// </summary> static void LongRunTask() { //Create a new thread instead of using threads in the thread pool Task task = new Task(TaskMethod, "Long running tasks", TaskCreationOptions.LongRunning); task.Start(); }
V. Outcomes of Tasks
/// <summary> /// Result of the task /// </summary> static void TaskResult() { Task<string> task = new Task<string>((name) => { Console.WriteLine(name); return string.Format("My name is:{0}", name); }, "Zhang San"); task.Start(); Console.WriteLine(task.Result); task.Wait(); }
6. Continuous tasks
/// <summary> /// Continuous Tasks /// </summary> static void ContinueTask() { Task task1 = new Task(() => { Console.WriteLine("Task Start:{0}", Task.CurrentId); Thread.Sleep(3000); }); //task1 Execute immediately after completion task2 Task task2 = task1.ContinueWith((task) => { Console.WriteLine("Complete tasks:", task.Id); Console.WriteLine("Current Task:", Task.CurrentId); Console.WriteLine("Do some cleanup"); Thread.Sleep(3000); }); task1.Start(); }
7. Task Hierarchy
/// <summary> /// Parent-Child Tasks /// </summary> static void ParentAndChildTask() { Task parent = new Task(ParentTask); parent.Start(); Thread.Sleep(2000); Console.WriteLine(parent.Status); Thread.Sleep(4000); Console.WriteLine(parent.Status); } static void ParentTask() { Console.WriteLine("Task number:", Task.CurrentId); Task child = new Task(ChildTask); child.Start(); Thread.Sleep(1000); Console.WriteLine("Start Subtask"); } static void ChildTask() { Console.WriteLine("Subtasks"); Thread.Sleep(5000); Console.WriteLine("Subtask Completion"); }
8. Cancel Tasks
//Cancel Task static void CancelTask() { CancellationTokenSource cts = new CancellationTokenSource(); cts.Token.Register(() => { Console.WriteLine("Execute after the task is cancelled"); }); Task task = new Task(() => { Console.WriteLine("Start Task"); for (int i = 0; i < 100; i++) { CancellationToken token = cts.Token; if (token.IsCancellationRequested) { Console.WriteLine("Task cancelled"); token.ThrowIfCancellationRequested(); } Thread.Sleep(100); Console.WriteLine("Cycle number:{0}", i); if (i == 5) cts.Cancel(); } }, cts.Token); task.Start(); try { task.Wait(); } catch (AggregateException ex) { Console.WriteLine("Exception:{0},{1}", ex.GetType().Name, ex.Message); foreach (var innerException in ex.InnerExceptions) { Console.WriteLine("Internal exception:{0},{1}", ex.InnerException.GetType().Name, ex.InnerException.Message); } } }
ThreadPool Thread Pool
static void ThreadPoolDemo() { int workerThreads; int completionPortThreads; ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); Console.WriteLine("Work Threads:{0},IO Threads:{1}", workerThreads, completionPortThreads); for (int i = 0; i < 5; i++) { ThreadPool.QueueUserWorkItem(TaskMethod); } } static void TaskMethod(object state) { for (int i = 0; i < 3; i++) { Console.WriteLine("Cycle:{0},Threads:{1}", i, Thread.CurrentThread.ManagedThreadId); } }
Thread class
1. Create a thread
/// <summary> /// Create a thread /// </summary> static void CreateThread() { Thread thread = new Thread(() => { Console.WriteLine("This is a thread,{0}", Thread.CurrentThread.ManagedThreadId); }); thread.Start(); Console.WriteLine("This is a main thread,{0}", Thread.CurrentThread.ManagedThreadId); }
2. Passing data to threads
1. Mode 1, using the Thread constructor with the ParameterizedThreadStart delegate parameter
/// <summary> /// Pass data to thread (mode 1) /// </summary> static void ThreadWithData1() { var data = new { Message = "This is a message" }; Thread thread = new Thread((state) => { var obj = (dynamic)state; Console.WriteLine(obj.Message); }); thread.Start(data); }
2. Mode 2, create a custom class that defines the thread's method as the instance method so that after initializing the instance's data, the thread can be started.
class MyThread { private string message = string.Empty; public MyThread(string message) { this.message = message; } public void ThreadMain() { Console.WriteLine(message); } }
/// <summary> /// Pass data to thread (mode 2) /// </summary> static void ThreadWithData2() { MyThread myThread = new MyThread("This is a message"); Thread thread = new Thread(myThread.ThreadMain); thread.Start(); }
3. Background Threads
/// <summary> /// Background Threads /// </summary> static void BackgroundThread() { Thread thread = new Thread(() => { Console.WriteLine("Thread starts:{0}",Thread.CurrentThread.Name); Thread.Sleep(3000); Console.WriteLine("Thread complete startup:{0}", Thread.CurrentThread.Name); }); thread.Name = "MyThread"; thread.IsBackground = true; thread.Start(); }