C# 使用线程池队列(学习笔记)

使用线程池队列(ThreadPool.QueueUserWorkItem())

  • 场景
  • 解决方案
    • A.SQL
    • B.控制台代码
    • C.Achievements
  • 资源

场景

  • 当初客户要求给自己的营业部和营业所推送邮件(收件人超1000个)
  • 邮件正文是去下载报表WORD(文件大小5M以上)数据文件转成HTML
  • 三个附件文件也是要去报表上下载EXCEL(文件大小3M以上)
  • 邮件要在10点之间推送完,但是这里报表的数据是8点以后ETL才刷好(数据刷好的时间不准确)

解决方案

  • 1000个邮箱用循环去跑肯定慢;就算1分钟10封邮件也发不完;而且也没有这么高的性能
  • 为了提高发送邮件的性能不得不去使用C#线程编程;我在这里使用了线程池这个东西,主要是因为线程池有队列、可以设置线程池中有多个线程一起做任务、线程池可以更好得控制CPU资源自己回收

A.SQL

CREATE DATABASE [SendEmailTest]

USE [SendEmailTest]
GO

CREATE TABLE [dbo].[mailboxUser](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[subject] [nvarchar](120) NULL,
	[mailBody] [nvarchar](255) NULL,
	[toEmail] [nvarchar](100) NULL,
	[toEmailBCC] [nvarchar](100) NULL,
	[State] [nchar](10) NULL,
	[Creater] [nvarchar](100) NULL,
	[CreateTime] [datetime] NULL,
	[Updater] [nvarchar](100) NULL,
	[UpdateTime] [datetime] NULL,
 CONSTRAINT [PK_mailboxUser] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO


DECLARE @count INT,@i INT
SET @count=120
SET @i=1

WHILE @i<=@count
BEGIN
	INSERT INTO [mailboxUser] VALUES 
	(
	'今天又是有希望得一天;'+CAST(@i AS NVARCHAR),
	'今天要把任务做完;'+CAST(@i AS NVARCHAR),
	'[email protected]',
	'',
	'1',
	'abel',
	GETDATE(),
	null,
	null
	)
	SET @i=@i+1
END

C# 使用线程池队列(学习笔记)_第1张图片

B.控制台代码

class Program
{
    private static string userEmail = ConfigHelper.GetConfigStr("userEmail"); //发件人邮箱
    private static string userPswd = ConfigHelper.GetConfigStr("userPswd"); //邮箱帐号密码
    private static string mailServer = ConfigHelper.GetConfigStr("mailServer"); //邮件服务器
    private static string attachFilesPath = ConfigHelper.GetConfigStr("attachFilesPath"); //文件地址
    private static string ServerDataDB = ConfigHelper.GetConfigStr("ServerDataDB");

    static void Main(string[] args)
    {
        Console.WriteLine("------------------------------------------------------------------------------1.程序开始");
        Stopwatch watch = new Stopwatch();
        watch.Start(); //开始监视
        ThreadUseAndConstruction();
        //StartSendMail(1,"test","邮件发送测试", "[email protected]","");
        watch.Stop(); //  停止监视
        Console.WriteLine("------------------------------------------------------------------------------2.程序结束");
        TimeSpan timespan = watch.Elapsed; //  获取当前实例测量得出的总时间
        Console.WriteLine("主线程运行结束;费时:" + timespan.TotalMilliseconds + "(总毫秒数)");
        Console.ReadLine();
    }

    /// 
    /// 启动推送邮件线程池方法 2020-10-15 11:03 abel
    /// 
    public static void ThreadUseAndConstruction()
    {
        //1.设置程序在运行时最小线程数和最大线程数
        ThreadPool.SetMinThreads(1, 1); 
        ThreadPool.SetMaxThreads(5, 5); 

        //2.查询推送的邮箱用户
        DataTable dt = new DbHelperSQL(ServerDataDB).Query(SelectMailboxUser_SQL).Tables[0];
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            int code = int.Parse(dt.Rows[i]["ID"].ToString());
            string subject = dt.Rows[i]["subject"].ToString();
            string mailBody = dt.Rows[i]["mailBody"].ToString();
            string toEmail = dt.Rows[i]["toEmail"].ToString();
            string toEmailBCC = dt.Rows[i]["toEmailBCC"].ToString();

            //3.把推送邮件的方法放入WaitCallback委托
            WaitCallback callback = index =>
            {
                Stopwatch watch = new Stopwatch();
                watch.Start(); //开始监视
                StartSendMail(code, subject, mailBody, toEmail, toEmailBCC);
                watch.Stop(); //  停止监视
                TimeSpan timespan = watch.Elapsed; //  获取当前实例测量得出的总时间
                Console.WriteLine("编号:" + code + "的邮件推送结束;费时:" + timespan.TotalMilliseconds + "(总毫秒数)");
            };

            //4.在线程池中加入线程队列
            ThreadPool.QueueUserWorkItem(callback, i);
        }
    }

    /// 
    /// 开始推送邮件 2020-10-15 10:30 abel
    /// 
    /// 用户邮箱ID
    /// 主题
    /// 内容
    /// 接收人
    /// 抄送人
    public static void StartSendMail(int code, string subject, string mailBody, string toEmail, string toEmailBCC) 
    {
        bool SendState = new EmailHelper(toEmail, toEmailBCC, subject, mailBody, new string[0], userEmail, userPswd, mailServer).SendEmail();
        if (SendState == true) 
            new DbHelperSQL(ServerDataDB).ExecuteSql(UpdateSendMailboxState_SQL, new SqlParameter[] { new SqlParameter("ID", code) });
    }

    /// 
    /// 查询推送的邮件用户 2020-10-15 10:52 abel
    /// 
    private const string SelectMailboxUser_SQL = "select * from [dbo].[mailboxUser] where [State]=1";

    /// 
    /// 更新邮件推送成功后的状态 2020-10-15 10:50 abel
    /// 
    private const string UpdateSendMailboxState_SQL = "update [dbo].[mailboxUser] set [State]='0',[Updater]='abel_2',[UpdateTime]=getdate() where [ID]=@ID";
}

C.Achievements

C# 使用线程池队列(学习笔记)_第2张图片
C# 使用线程池队列(学习笔记)_第3张图片
C# 使用线程池队列(学习笔记)_第4张图片

资源

百度网盘链接地址:https://pan.baidu.com/s/1_vJB3tXta42t52f39fAiZQ
提取码:bhss

你可能感兴趣的:(C#)