并发生成验证码图片,保证并发也生成不同

/*
并发验证码生成,即使并发也不会相同
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));
    }
}


你可能感兴趣的:(并发,验证码)