Threads (asynchronous and multithreaded)

Keywords: C# Database Attribute less

Task is. NET Framework 3.0. Threads are based on thread pools and then provide rich api s. Thread methods are very powerful, but they are too powerful and unrestricted.

The DoSomething Long method is as follows:

 /// <summary>
 /// A more time-consuming and resource-consuming private approach
 /// </summary>
 /// <param name="name"></param>
 private void DoSomethingLong(string name)
 {
     Console.WriteLine($"****************DoSomethingLong Start  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
     long lResult = 0;
     for (int i = 0; i < 1_000_000_000; i++)
     {
         lResult += i;
     }
     Thread.Sleep(2000);

     Console.WriteLine($"****************DoSomethingLong   End  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
 }

Use of Task:

{
    Task task = new Task(() => this.DoSomethingLong("btnTask_Click_1"));
    task.Start();
}
{
    Task task = Task.Run(() => this.DoSomethingLong("btnTask_Click_2"));
}
{
    TaskFactory taskFactory = Task.Factory;
    Task task = taskFactory.StartNew(() => this.DoSomethingLong("btnTask_Click_3"));
}

 

 

If this is called:

ThreadPool.SetMaxThreads(8, 8);
for (int i = 0; i < 100; i++)
{
    int k = i;
    Task.Run(() =>
    {
        Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        Thread.Sleep(2000);
    });
}

 

 

If you remove the code that sets the maximum thread:

for (int i = 0; i < 100; i++)
{
    int k = i;
    Task.Run(() =>
    {
        Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        Thread.Sleep(2000);
    });
}

The results are as follows:

 

 

 

 ThreadPool.SetMaxThreads(8, 8);

Thread pool is singular and globally unique. After setting up, there are only 8 concurrent Tasks, which are reusable. Task threads originate from thread pool. Global, please do not set up this way.

What if I want to control the number of concurrencies in Task?

{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    Console.WriteLine("stay Sleep before");
    Thread.Sleep(2000);//Synchronous waiting--Current thread waits for 2 s Then proceed
    Console.WriteLine("stay Sleep after");
    stopwatch.Stop();
    Console.WriteLine($"Sleep time consuming{stopwatch.ElapsedMilliseconds}");
}
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    Console.WriteLine("stay Delay before");
    Task task = Task.Delay(2000)
        .ContinueWith(t =>
        {
            stopwatch.Stop();
            Console.WriteLine($"Delay time consuming{stopwatch.ElapsedMilliseconds}");

            Console.WriteLine($"This is ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        });//Asynchronous wait--Wait 2 s Start a new task later
    Console.WriteLine("stay Delay after");
    stopwatch.Stop();
    Console.WriteLine($"Delay time consuming{stopwatch.ElapsedMilliseconds}");
}

The results are as follows:

  

 

If the last stop watch is commented out:

 

 {
     Stopwatch stopwatch = new Stopwatch();
     stopwatch.Start();
     Console.WriteLine("stay Sleep before");
     Thread.Sleep(2000);//Synchronous waiting--Current thread waits for 2 s Then proceed
     Console.WriteLine("stay Sleep after");
     stopwatch.Stop();
     Console.WriteLine($"Sleep time consuming{stopwatch.ElapsedMilliseconds}");
 }
 {
     Stopwatch stopwatch = new Stopwatch();
     stopwatch.Start();
     Console.WriteLine("stay Delay before");
     Task task = Task.Delay(2000)
         .ContinueWith(t =>
         {
             stopwatch.Stop();
             Console.WriteLine($"Delay time consuming{stopwatch.ElapsedMilliseconds}");

             Console.WriteLine($"This is ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
         });//Asynchronous wait--Wait 2 s Start a new task later
     Console.WriteLine("stay Delay after");
     //stopwatch.Stop();
     //Console.WriteLine($"Delay time consuming{stopwatch.ElapsedMilliseconds}");
 }

 

 

 

When to use multithreading?

Task concurrency is the time

What can multithreading do?

Increase speed and optimize user experience.

 

For example, there is a scenario in which leaders can not assign tasks concurrently in company meetings, because only one leader can assign tasks in speech. When tasks are assigned, developers can start coding at the same time. This can be concurrent.

 TaskFactory taskFactory = new TaskFactory();
 List<Task> taskList = new List<Task>();
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle1", "Portal")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle2", "  DBA ")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle3", "Client")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle4", "BackService")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle5", "Wechat")));

 

Now ask who is the first to finish and get the ContinueWhenAny; after all, celebrate it together and put it in a List < Task>.

 TaskFactory taskFactory = new TaskFactory();
 List<Task> taskList = new List<Task>();
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle1", "Portal")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle2", "  DBA ")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle3", "Client")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle4", "BackService")));
 taskList.Add(taskFactory.StartNew(() => this.Coding("bingle5", "Wechat")));

 //Who's the first to finish and get a red envelope award?
 taskFactory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine($"XXX Complete the development and get a bonus package{Thread.CurrentThread.ManagedThreadId.ToString("00")}"));
 //After the project is completed, celebrate together
 taskList.Add(taskFactory.ContinueWhenAll(taskList.ToArray(), rArray => Console.WriteLine($"Development is complete. Celebrate together.{Thread.CurrentThread.ManagedThreadId.ToString("00")}")));

ContinueWhenAny ContinueWhenAll is a non-blocking callback; and the thread used may be a new thread or a thread that has just completed a task, and the only thread that can't be the main thread

//Blocking the current thread, waiting for any task to complete
Task.WaitAny(taskList.ToArray());//You can also wait for a limited time.
Console.WriteLine("Prepare the environment for deployment");
//You need to be able to wait for all threads to complete tasks before continuing to block the current threads until all tasks are completed.
Task.WaitAll(taskList.ToArray());
Console.WriteLine("5 After the completion of all modules, focus on comments");

 

Task.WaitAny WaitAll blocks the current thread, performs operations after the completion of the task, and blockages the card interface for concurrency and sequential control. Home page of the website: A database B interface C distributed service D search engine, suitable for multi-threaded concurrency, can be returned to users only after they have completed, and they need to wait for WaitAll, list. Page: Core data may come from database/interface service/distributed search engine/cache, multi-threaded concurrent requests, whichever is completed first, whichever is the other.

If I want to control the number of concurrent Task s, what should I do? 20

 List<Task> taskList = new List<Task>();
 for (int i = 0; i < 10000; i++)
 {
     int k = i;
     if (taskList.Count(t => t.Status != TaskStatus.RanToCompletion) >= 20)
     {
         Task.WaitAny(taskList.ToArray());
         taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
     }
     taskList.Add(Task.Run(() =>
     {
         Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
         Thread.Sleep(2000);
     }));
 }

 

Parallel executes multiple Action threads concurrently, and the main thread participates in the computation - blocking interface. Equivalent to TaskWaitAll + Main Thread Computing

 Parallel.Invoke(() => this.DoSomethingLong("btnParallel_Click_1"),
     () => this.DoSomethingLong("btnParallel_Click_2"),
     () => this.DoSomethingLong("btnParallel_Click_3"),
     () => this.DoSomethingLong("btnParallel_Click_4"),
     () => this.DoSomethingLong("btnParallel_Click_5"));
Parallel.For(0, 5, i => this.DoSomethingLong($"btnParallel_Click_{i}"));
Parallel.ForEach(new int[] { 0, 1, 2, 3, 4 }, i => this.DoSomethingLong($"btnParallel_Click_{i}"));

ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 3;
Parallel.For(0, 10, options, i => this.DoSomethingLong($"btnParallel_Click_{i}"));

Is there any way not to block?

Task.Run(() =>
{
    ParallelOptions options = new ParallelOptions();
    options.MaxDegreeOfParallelism = 3;
    Parallel.For(0, 10, options, i => this.DoSomethingLong($"btnParallel_Click_{i}"));
});

Almost 90% of multi-threaded scenarios, as well as sequential control, the above Task method can be completed, if your multi-threaded scenarios are too complex, please sort out your process and simplify it. It is suggested that threads should not be nested threads. If you can barely understand threads two or three times, the three layers will not hold, and more can only pray for God.

 

Multithread exceptions:

try
{

    List<Task> taskList = new List<Task>();
    for (int i = 0; i < 100; i++)
    {
        string name = $"btnThreadCore_Click_{i}";
        taskList.Add(Task.Run(() =>
        {
            if (name.Equals("btnThreadCore_Click_11"))
            {
                throw new Exception("btnThreadCore_Click_11 abnormal");
            }
            else if (name.Equals("btnThreadCore_Click_12"))
            {
                throw new Exception("btnThreadCore_Click_12 abnormal");
            }
            else if (name.Equals("btnThreadCore_Click_38"))
            {
                throw new Exception("btnThreadCore_Click_38 abnormal");
            }
            Console.WriteLine($"This is {name}Success ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }));
    }
    //Exceptions thrown in multithreading will terminate the current thread, but will not affect other threads.
    //Where is the thread exception? It's swallowed up.
    //If I want to get exception information, I need to notify other threads.
    Task.WaitAll(taskList.ToArray());//1 Thread exceptions can be caught
}
catch (AggregateException aex)//2 Need try-catch-AggregateException
{
    foreach (var exception in aex.InnerExceptions)
    {
        Console.WriteLine(exception.Message);
    }
}
catch (Exception ex)//Can more catch  First concrete then complete
{
    Console.WriteLine(ex);
}
//Thread exceptions often require notification to other threads rather than waiting WaitAll,The problem is to cancel the thread.
//Work routine recommendations: multi-threaded delegation does not allow exceptions, wrap a layer try-catch,Then record the exception information and complete the required operation.

Thread cancellation:

                //Multithread concurrent tasks, after a failure, want to notify other threads, all stop. how?
                //Thread.Abort--Terminate the thread; throw an exception to the current thread and terminate the task; the thread belongs to OS Resources may not stop immediately
                //Task You can't terminate tasks externally, you can only terminate yourself.(God can defeat himself)

                //cts There is bool attribute IsCancellationRequested Initialization is false
                //call Cancel After the method becomes true(Can't change back),Can repeat cancel
                try
                {
                    CancellationTokenSource cts = new CancellationTokenSource();
                    List<Task> taskList = new List<Task>();
                    for (int i = 0; i < 50; i++)
                    {
                        string name = $"btnThreadCore_Click_{i}";
                        taskList.Add(Task.Run(() =>
                        {
                            try
                            {
                                if (!cts.IsCancellationRequested)
                                    Console.WriteLine($"This is {name} start ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");

                                Thread.Sleep(new Random().Next(50, 100));

                                if (name.Equals("btnThreadCore_Click_11"))
                                {
                                    throw new Exception("btnThreadCore_Click_11 abnormal");
                                }
                                else if (name.Equals("btnThreadCore_Click_12"))
                                {
                                    throw new Exception("btnThreadCore_Click_12 abnormal");
                                }
                                else if (name.Equals("btnThreadCore_Click_13"))
                                {
                                    cts.Cancel();
                                }
                                if (!cts.IsCancellationRequested)
                                {
                                    Console.WriteLine($"This is {name}Successful conclusion ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                                }
                                else
                                {
                                    Console.WriteLine($"This is {name}Stop halfway ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                                    return;
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                                cts.Cancel();
                            }
                        }, cts.Token));
                    }
                    //1 Get ready cts  2 try-catch-cancel  3 Action Judge at any time IsCancellationRequested
                    //Stop as soon as possible, there must be a delay, in the judgment link will end.

                    Task.WaitAll(taskList.ToArray());
                    //If the thread hasn't started yet, can you stop it?
                    //1 Start thread delivery Token  2 Abnormal grasp  
                    //stay Cancel When a task has not been started, it will not be started; it will also throw an exception. cts.Token.ThrowIfCancellationRequested
                }
                catch (AggregateException aex)
                {
                    foreach (var exception in aex.InnerExceptions)
                    {
                        Console.WriteLine(exception.Message);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

Temporary variables:

 for (int i = 0; i < 5; i++)
 {
     Task.Run(() =>
     {
         Console.WriteLine($"This is btnThreadCore_Click_{i} ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
     });
 }

 

Why is the result 5?

For temporary variables, threads are non-blocking and start late; when threads execute, i is already 5

So how to solve it?

Each time a variable K is declared to receive, K is a variable in the closure, and each cycle has an independent k, five K variables and one i variable.

for (int i = 0; i < 5; i++)
{
    int k = i;
    Task.Run(() =>
    {
        Console.WriteLine($"This is btnThreadCore_Click_{i}_{k} ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
    });
}

If it runs again, the result will be normal.

 

Thread Safety & lock:

Thread Safety: If your code runs this section at the same time with multiple threads in the process, it is thread safe if the results of each run are consistent with those of a single thread.

Thread security issues generally have global variables / shared variables / static variables / hard disk files / database values, as long as multiple threads can access and modify

It happens because multiple threads operate the same way and override occurs. How to solve this problem?

1 Lock Resolves Multithread Conflicts

Lock is grammatical sugar, Monitor.Enter, occupies a reference, other threads can only wait.

The recommended lock is private static readonly object.

A can't be Null, can compile and can't run;

B does not recommend lock(this). If you use instances outside, it will conflict.

//Test test = new Test();
//Task.Delay(1000).ContinueWith(t =>
//{
//    lock (test)
//    {
//        Console.WriteLine("*********Start**********");
//        Thread.Sleep(5000);
//        Console.WriteLine("*********End**********");
//    }
//});
//test.DoTest();

//C It should not be string; string Reuse in memory allocation and conflict
//D Lock There's not too much code in it. Here's a single thread.
Test test = new Test();
string student = "Sliced Fish in Hot Chili Oil";
Task.Delay(1000).ContinueWith(t =>
{
    lock (student)
    {
        Console.WriteLine("*********Start**********");
        Thread.Sleep(5000);
        Console.WriteLine("*********End**********");
    }
});
test.DoTestString();
//2 Thread Safety Set
//System.Collections.Concurrent.ConcurrentQueue<int>

//3 Data splitting to avoid multi-threaded operation of the same data; safe and efficient

for (int i = 0; i < 10000; i++)
{
    this.iNumSync++;
}
for (int i = 0; i < 10000; i++)
{
    Task.Run(() =>
    {
        lock (Form_Lock)//Only one thread can enter a method block at any time, which is not a single thread.
        {
            this.iNumAsync++;
        }
    });
}
for (int i = 0; i < 10000; i++)
{
    int k = i;
    Task.Run(() => this.iListAsync.Add(k));
}

Thread.Sleep(5 * 1000);
Console.WriteLine($"iNumSync={this.iNumSync} iNumAsync={this.iNumAsync} listNum={this.iListAsync.Count}");
//iNumSync and  iNumAsync What is 9981, respectively?/9988  1 To less than 10,000

Posted by spadmore on Fri, 20 Sep 2019 07:43:50 -0700