What is.net multithreading?

Processes and threads

A process is a program in progress.

A thread is a flow of execution within a program.

Multithreading refers to the ability to run multiple threads simultaneously in a program to perform different tasks.

Threads in.net

Threads are classes that create and control threads.

ManagedThreadId is the thread ID.

CurrentThread is the thread that is currently running.

Synchronous and asynchronous

Synchronization is when once the call has started, the caller must wait until the method call returns before continuing with the subsequent behavior. (Single thread)

Once the asynchronous invocation begins, the method invocation returns immediately and the caller can continue with subsequent operations. (Multithreading)

Development of multithreading in.NET

There are threads, threadPools, and tasks

Threads are threads that need to be scheduled by themselves and directly connected to the system, which is relatively complex and inefficient to manage.

Threadpools are updated versions of threads. Threadpools fetch threads from a Thread pool and are called if there are any free elements in the pool. Threadpools create threads all the time. Keep in mind that starting a thread without doing anything consumes around 1m memory, which is a huge waste of performance. However, ThreadPool provides fewer interfaces.

A Task is the same as a ThreadPool in that it fetches idle threads from a ThreadPool. Richer than the ThreadPool call interface. Currently.Net uses multi-threaded management, so Task should be preferred.

Code:

/ / / < summary > / / / multithreaded development history / / / < summary > / / / < param name = "sender" > < param > / / / < param name = "e" > < param > private void btnHistory_Click(object sender, EventArgs e) { Console.WriteLine($"Thread start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); var threadStart = new ThreadStart(DoNothing); var thread = new Thread(threadStart); thread.Start(); Console.WriteLine($"Thread end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Thread.Sleep(3000); Console.WriteLine($"ThreadPool start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); var callback = new WaitCallback(DoNothing); ThreadPool.QueueUserWorkItem(callback); Console.WriteLine($"ThreadPool end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Thread.Sleep(3000); Console.WriteLine($"Task start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Action action = DoNothing; Task task = new Task(action); task.Start(); Console.WriteLine($"Task end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); }Copy the code

Why multithreading?

Features:

  • Card interface: single thread card, multi-thread card
  • Good performance: poor single-thread, good multi-thread (resource for performance)
  • Execution order: single-thread order, multi-thread disorder

Code:

/ / / < summary > synchronous (single-threaded) / / / / / / < summary > / / / < param name = "sender" > < param > / / / < param name = "e" > < param > private void btnSync_Click(object sender, EventArgs e) { Console.WriteLine($"btnSync_Click start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); for (int i = 0; i < 5; i++) { DoNothing(); } Console.WriteLine($"btnSync_Click end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); } / / / < summary > asynchronous (multithreaded) / / / / / / < summary > / / / < param name = "sender" > < param > / / / < param name = "e" > < param > private void btnAsync_Click(object sender, EventArgs e) { Console.WriteLine($"btnAsync_Click start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}");  for (int i = 0; i < 5; i++) { var ts = new ThreadStart(DoNothing); var t = new Thread(ts); t.Start(); } Console.WriteLine($"btnAsync_Click end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); } private void DoNothing() { Console.WriteLine($"DoNothing start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Thread.Sleep(2000); Console.WriteLine($"DoNothing end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); }Copy the code

How to use.NET multithreading?

Task

Create a task

Instantiate by calling the task class constructor, but Start the task by calling its Start().

Task t1 = new Task(action, "alpha");
t1.Start();
Copy the code

2. Instantiate and start tasks in a single method call by calling taskFactory.startNew (Action, Object).

Task t2 = Task.Factory.StartNew(action, "beta");
Copy the code

3. Instantiate and start tasks in a single method call by calling the Run (Action) method.

Task t3 = Task.Run(action);
Copy the code

Returns a value from the task

The Result property blocks the calling thread until the task completes.

Task<int> task1 = Task<int>.Factory.StartNew(() => 1);
int i = task1.Result;
Copy the code

Waiting for the task to complete

The Wait method can be called to Wait for one or more tasks to complete, synchronizing the execution of the calling thread with the asynchronous tasks it starts.

Call the no-argument Wait() method to Wait unconditionally until the task completes.

Calling the Wait(Int32) and Wait(TimeSpan) methods blocks the calling thread until the task is complete or the timeout interval, whichever comes first.

Call the WaitAny(Task[]) method to wait for the first Task in a set of tasks to complete.

Call the WaitAll(Task[]) method to wait for a series of tasks to complete.

Exception handling

The calling code can handle exceptions by using any of the following methods in the try/catch block:

  • await task
  • task.Wait()
  • task.Result
  • task.GetAwaiter().GetResult()

Code:

var task1 = Task.Run(() => { throw new Exception("This exception is expected!" ); }); try { task1.Wait(); } catch (Exception e) { Console.WriteLine(e.Message); } Console.ReadKey();Copy the code

Cancel the task

You can use the CancellationTokenSource class to make a cancellation request at a later time.

static void Main(string[] args) { var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var tasks = new ConcurrentBag<Task>(); Task tc; for (int i = 0; i < 10; i++) { var k = i; tc = Task.Run(() => DoNothing(k, token), token); tasks.Add(tc); } char ch = Console.ReadKey().KeyChar; if (ch == 'c' || ch == 'C') { tokenSource.Cancel(); Console.WriteLine("\n Start to cancel the task."); } try { Task.WhenAll(tasks.ToArray()); } catch (OperationCanceledException) { Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n"); } finally { tokenSource.Dispose(); } Console.ReadKey(); } private static void DoNothing(int i, CancellationToken ct) { Console.WriteLine($"DoNothing start index:{i} id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Thread.Sleep(i * 1000); If (ct) IsCancellationRequested) {Console. WriteLine ($" task has cancelled the index: {I}, {Thread. CurrentThread. ManagedThreadId} "); ct.ThrowIfCancellationRequested(); } Console.WriteLine($"DoNothing end index:{i} id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); }Copy the code

The actual case

Code:

/ / / < summary > / / / / / / Task of the actual cases < summary > / / / < param name = "sender" > < param > / / / < param name = "e" > < param > private void btnTask_Click(object sender, EventArgs e) {Console. WriteLine ($" project received task id: {Thread. CurrentThread. ManagedThreadId} time: {DateTime. Now} "); Console. WriteLine ($" project manager database design, prototype design, allocation of task id: {Thread. CurrentThread. ManagedThreadId} time: {DateTime. Now} "); List<Task> tasks = new List<Task>(); Tasks.add (task.run (() => Coding(" zhao XX"," front-end page "))); The tasks. The Add (Task. Run (() = > Coding (" XX "king," IOS page "))); Tasks. The Add (Task. Run (() = > Coding (" XX "yellow," backend interface "))); The tasks. The Add (Task. Run (() = > Coding (" XX "du," backend interface "))); TaskFactory taskFactory = new TaskFactory(); TaskFactory. ContinueWhenAll (tasks. ToArray (), t = > {Console. WriteLine ($" project manager, Testers testing task id: {Thread. CurrentThread. ManagedThreadId} time: {DateTime. Now} "); }); } private void Coding(string personName,string taskName) {console. WriteLine($"{personName} dev {taskName} id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Thread.Sleep(2000); }Copy the code

Async and await

Async and Await are created in almost the same way as synchronous methods.

Code:

/ / / < summary > / / / / / / Async and Await application < summary > / / / < param name = "sender" > < param > / / / < param name = "e" > < param > private void btnAsyncAndAwait_Click(object sender, EventArgs e) { Console.WriteLine($"btnAsyncAndAwait_Click start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); DoNothingAsync(); Console.WriteLine($"btnAsyncAndAwait_Click end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); } private async Task DoNothingAsync() { Console.WriteLine($"DoNothingAsync start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); await Task.Run(() => { Console.WriteLine($"DoNothingAsync Task start id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); Thread.Sleep(2000); Console.WriteLine($"DoNothingAsync Task end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); }); Console.WriteLine($"DoNothingAsync end id:{Thread.CurrentThread.ManagedThreadId} time:{DateTime.Now}"); }Copy the code

reference

  • Task-based asynchronous mode docs.microsoft.com/zh-CN/dotne…
  • Asynchronous programming with Async and Await docs.microsoft.com/zh-CN/dotne…