CPU 100% 问题分析,我们把博客园踩过的坑又踩了一遍《二》(补充)

问题如下:

针对.net core 异常奇怪问题分析

1、StackExchange.Redis.RedisConnectionException: It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. Timeout
at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(Func`1 multiplexerFactory, TextWriter log)

2、There is already an open DataReader associated with this Command which must be closed first

3、A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be

static void Main(string[] args)
        {
          //按键后开始执行
            Console.ReadKey();
            //模拟并发
            while (true)
            {
                Task.Run(Producer);
                Thread.Sleep(200);
            }
           
        }
        /// <summary>
        /// 如果处理程序耗时>请求耗时,也就是说引起并发,就会导致死锁
        /// </summary>
        static void Producer()
        {
            var result = Process().Result;
            //或者
            //Process().Wait();
        }


        static async Task<bool> Process()
        {
            Console.WriteLine("Start - " + DateTime.Now.ToLongTimeString());
            await Task.Run(() =>
            {
                //模拟任务执行耗时
                Thread.Sleep(1000);
            });

            Console.WriteLine("Ended - " + DateTime.Now.ToLongTimeString());
            return true;
        }        

 

执行效果:

以上可看出:

1、控制台执行5-10个任务后,不再执行Ended 语句的任何内容(Ended语句全部被阻塞)

2、内存占用稳步上升

3、AsyncTest.exe 线程每秒增加一个

 

解决方案:

var result = Process().ConfigureAwait(false);

或修改为异步方法(强烈推荐

     static async Task Producer()
        {
            await Process();
        }

 ---补充 2021.2.26-------------------

优化代码后进一步测试

测试代码如下:

  1 using System;
  2 using System.Threading;
  3 using System.Threading.Tasks;
  4 
  5 namespace AsyncTest
  6 {
  7     class Program
  8     {
  9         static void Main(string[] args)
 10         {
 11             Console.ReadKey();
 12             //模拟并发
 13             for (int i = 0; i < 300; i++)
 14             {
 15                
 16                 Task.Run(() => 
 17                      Producer(i)
 18                 );
 19                 // Task.Run(Producer3);
 20                 // Task.Run(ProducerQueue);
 21                 Thread.Sleep(300);
 22             }
 23         }
 24         /// <summary>
 25         /// 如果处理程序耗时>请求耗时,也就是说引起并发,就会导致死锁
 26         /// </summary>
 27         static void Producer(int i)
 28         {
 29             var result = Process(i).Result;
 30             //或者
 31             //Process().Wait();
 32         }
 33         /// <summary>
 34         /// 正常
 35         /// </summary>
 36         static void Producer2(int i)
 37         {
 38             var result = Process(i).ConfigureAwait(false);
 39         }
 40         //cpu 内存均正常
 41         static async Task Producer3(int i)
 42         {
 43             await Process(i);
 44         }
 45 
 46         /// <summary>
 47         /// 
 48         /// </summary>
 49         static void ProducerQueue(int i)
 50         {
 51             ProcessQueue(i).Wait();
 52             //或者
 53             //Process().Wait();
 54         }
 55         /// <summary>
 56         /// 正常
 57         /// </summary>
 58         static void ProducerQueue2(int i)
 59         {
 60             var result = ProcessQueue(i).ConfigureAwait(false);
 61         }
 62         //cpu 内存均正常
 63         static async Task ProducerQueue3(int i)
 64         {
 65             await ProcessQueue(i);
 66         }
 67 
 68         static async Task<bool> Process(int i)
 69         {
 70             ConsoleWrite($"Start{i}");
 71             await Task.Run(() =>
 72             {
 73                 //模拟任务执行耗时
 74                 Thread.Sleep(2000);
 75             });
 76 
 77             ConsoleWrite($"End{i}");
 78             return true;
 79         }
 80 
 81 
 82 
 83         static async Task ProcessQueue(int i)
 84         {
 85             ConsoleWrite($"Start{i}");
 86             ThreadPool.QueueUserWorkItem(state =>
 87             {
 88                 ConsoleWrite("Hello" + (string)state);
 89             }, await GetName(i));
 90             ConsoleWrite($"End{i}");
 91         }
 92 
 93         private static async Task<string> GetName(int i)
 94         {
 95             Thread.Sleep(1000);
 96             Random r = new Random();
 97             return $"ZhiXin[{r.Next(100, 999)}]-[{i}]";
 98         }
 99         private static string GetCurrentThreadID()
100         {
101             return $" {DateTime.Now.ToLongTimeString()} --ThreadId[{Thread.CurrentThread.ManagedThreadId.ToString("0000")}]";
102         }
103         private static void ConsoleWrite(string type)
104         {
105             if (type.Contains("Start"))
106             {
107                 //Console.BackgroundColor = ConsoleColor.Blue; //设置背景色
108                 Console.ForegroundColor = ConsoleColor.Green; //设置前景色,即字体颜色
109             }
110             else if (type.Contains("End"))
111             {
112                 // Console.BackgroundColor = ConsoleColor.Red; //设置背景色
113                 Console.ForegroundColor = ConsoleColor.Red; //设置前景色,即字体颜色
114             }
115             Console.WriteLine($"{type} - " + GetCurrentThreadID());
116         }
117     }
118 }
使用.Result异步调用

结果如下:

测试代码如下:

  1 using System;
  2 using System.Threading;
  3 using System.Threading.Tasks;
  4 
  5 namespace AsyncTest
  6 {
  7     class Program
  8     {
  9         static void Main(string[] args)
 10         {
 11             Console.ReadKey();
 12             //模拟并发
 13             for (int i = 0; i < 300; i++)
 14             {
 15                
 16                 Task.Run(() => 
 17                      Producer3(i)
 18                 );
 19                 // Task.Run(Producer3);
 20                 // Task.Run(ProducerQueue);
 21                 Thread.Sleep(300);
 22             }
 23         }
 24         /// <summary>
 25         /// 如果处理程序耗时>请求耗时,也就是说引起并发,就会导致死锁
 26         /// </summary>
 27         static void Producer(int i)
 28         {
 29             var result = Process(i).Result;
 30             //或者
 31             //Process().Wait();
 32         }
 33         /// <summary>
 34         /// 正常
 35         /// </summary>
 36         static void Producer2(int i)
 37         {
 38             var result = Process(i).ConfigureAwait(false);
 39         }
 40         //cpu 内存均正常
 41         static async Task Producer3(int i)
 42         {
 43             await Process(i);
 44         }
 45 
 46         /// <summary>
 47         /// 
 48         /// </summary>
 49         static void ProducerQueue(int i)
 50         {
 51             ProcessQueue(i).Wait();
 52             //或者
 53             //Process().Wait();
 54         }
 55         /// <summary>
 56         /// 正常
 57         /// </summary>
 58         static void ProducerQueue2(int i)
 59         {
 60             var result = ProcessQueue(i).ConfigureAwait(false);
 61         }
 62         //cpu 内存均正常
 63         static async Task ProducerQueue3(int i)
 64         {
 65             await ProcessQueue(i);
 66         }
 67 
 68         static async Task<bool> Process(int i)
 69         {
 70             ConsoleWrite($"Start{i}");
 71             await Task.Run(() =>
 72             {
 73                 //模拟任务执行耗时
 74                 Thread.Sleep(2000);
 75             });
 76 
 77             ConsoleWrite($"End{i}");
 78             return true;
 79         }
 80 
 81 
 82 
 83         static async Task ProcessQueue(int i)
 84         {
 85             ConsoleWrite($"Start{i}");
 86             ThreadPool.QueueUserWorkItem(state =>
 87             {
 88                 ConsoleWrite("Hello" + (string)state);
 89             }, await GetName(i));
 90             ConsoleWrite($"End{i}");
 91         }
 92 
 93         private static async Task<string> GetName(int i)
 94         {
 95             Thread.Sleep(1000);
 96             Random r = new Random();
 97             return $"ZhiXin[{r.Next(100, 999)}]-[{i}]";
 98         }
 99         private static string GetCurrentThreadID()
100         {
101             return $" {DateTime.Now.ToLongTimeString()} --ThreadId[{Thread.CurrentThread.ManagedThreadId.ToString("0000")}]";
102         }
103         private static void ConsoleWrite(string type)
104         {
105             if (type.Contains("Start"))
106             {
107                 //Console.BackgroundColor = ConsoleColor.Blue; //设置背景色
108                 Console.ForegroundColor = ConsoleColor.Green; //设置前景色,即字体颜色
109             }
110             else if (type.Contains("End"))
111             {
112                 // Console.BackgroundColor = ConsoleColor.Red; //设置背景色
113                 Console.ForegroundColor = ConsoleColor.Red; //设置前景色,即字体颜色
114             }
115             Console.WriteLine($"{type} - " + GetCurrentThreadID());
116         }
117     }
118 }
使用await关键字异步调用

 

结果如下:

 

 

 

 ps:截屏工具 ScreenToGif

参考:

又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)

一码阻塞,万码等待:ASP.NET Core 同步方法调用异步方法“死锁”的真相

.NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长

 C#同步方法中如何调用异步方法?值得一看

 理解C#中的ConfigureAwait

 bindot:https://www.cnblogs.com/bindot/p/cpu100.html

posted @ 2021-02-02 16:22  FengLu-1  阅读(1223)  评论(4编辑  收藏  举报