/*并发验证码生成,即使并发也不会相同1秒并发100测试通过没有重复没有报错,内存增加40mb左右,增加到80mb后就基本不再增加*/using System;using System.Drawing;using System.Threading.Tasks;using System.Collections.Concurrent;public class CheckCode : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { if (Request["w"] || Request["h"])//重写这里保证输入的都是数字,图片宽高 return; int imgWidth = int.Parse(Request["w"]); int imgHeight = int.Parse(Request["h"]); string tmp = GenerateCheckCode(); Session["checkcode"] = tmp + "|" + DateTime.Now.ToString(); this.CreateCheckCodeImage(tmp, imgWidth, imgHeight); } //这段随机验证码生成程序可以另外写,重点是后面的图片生成 private string GenerateCheckCode() { int number; char code; string checkCode = String.Empty; System.Random random = new Random(Seed()); for (int i = 0; i < 5; i++) { REBUILD: number = random.Next(); if (number % 2 == 0) code = (char)('0' + (char)(number % 10)); else code = (char)('A' + (char)(number % 26)); if (code == '0' || code == 'O') goto REBUILD; checkCode += code.ToString(); } //Response.Cookies.Add(new HttpCookie("CheckCode", checkCode)); return checkCode; } //生成图片,并写入验证码 private void CreateCheckCodeImage(string checkCode, int imgW, int imgH) { if (string.IsNullOrWhiteSpace(checkCode)) return; System.Drawing.Bitmap image = new System.Drawing.Bitmap(imgW, imgH); Graphics g = Graphics.FromImage(image); object o = new object(); System.IO.MemoryStream ms = new System.IO.MemoryStream(); try { int pc = Environment.ProcessorCount;//用并发,知道cpu核心数 // 清空图片背景色 g.Clear(Color.White); // 画图片的背景噪音线 int parallelCount = pc * 4;//4倍cpu核心数的线条,并发写入 Parallel.ForEach(Partitioner.Create(0, parallelCount, ((int)(parallelCount / pc) + 1)), range => { for (int i = range.Item1; i < range.Item2; i++) { Random random = new Random(Seed()); int x1 = random.Next(imgW); int x2 = random.Next(imgW); int y1 = random.Next(imgH); int y2 = random.Next(imgH); Pen p = new Pen(Color.FromArgb(random.Next())); lock (o) { g.DrawLine(p, x1, y1, x2, y2); } p.Dispose(); p = null; random = null; } }); //并发画验证码和外边框 Parallel.Invoke(() => { //写验证码 Font font = new System.Drawing.Font("Arial", 12, (System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic)); Color c1 = Color.Blue; Color c2 = Color.DarkRed; System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, imgW, imgH), c1, c2, 1.2f, true); SizeF strSize = new SizeF(); lock (o) { strSize = g.MeasureString(checkCode, font); } float left = (imgW - strSize.Width) / 2; float top = (imgH - strSize.Height) / 2; lock (o) { g.DrawString(checkCode, font, brush, left, top); } //回收 font.Dispose(); font = null; brush.Dispose(); brush = null; }, () => { // 画图片的边框线 lock (o) { g.DrawRectangle(new Pen(Color.Silver), 0, 0, imgW - 1, imgH - 1); } }); // 画图片的前景噪音点,并发画噪点,16倍cpu核心数的噪点。 parallelCount = pc * 16; Parallel.ForEach(Partitioner.Create(0, parallelCount, ((int)(parallelCount / pc) + 1)), range => { for (int i = range.Item1; i < range.Item2; i++) { Random random = new Random(Seed()); int x = random.Next(imgW); int y = random.Next(imgH); lock (o) { image.SetPixel(x, y, Color.FromArgb(random.Next())); } random = null; } }); //写入流 image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif); Response.ClearContent(); Response.ContentType = "image/gif"; Response.BinaryWrite(ms.ToArray()); } finally { //下面全是提示回收的, g.Dispose(); g = null; image.Dispose(); image = null; o = null; ms.Dispose(); ms = null; GC.Collect(); } } //并发随机种子数生成 public int Seed() { byte[] bytes = new byte[4]; System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); rng.GetBytes(bytes); return System.Math.Abs(BitConverter.ToInt32(bytes, 0)); }}