程序设计范式五
假定有一个
固定大小
的
缓冲区
(如库房或中间商),生产者向缓冲区添加数据(入库),消费者从缓冲区删除数据(出库)
编程模拟生产和消费过程
代码实现需要考虑存储问题,在给加水印后的图片存入指定文件夹重新命名时可以修改为使用uid或者时间轴命名,保证唯一性,下面代码未修改命名方式
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static SemaphoreSlim occupied=new SemaphoreSlim(0);//生产者信号量
private static SemaphoreSlim unoccupied = new SemaphoreSlim(Max);//消费者信号量
static int putin = 0;//存入位置指示器
static int takeout = 0;//取出位置指示器
const int Max = 100;//缓冲区大小
static string[] arrFiles = new string[Max];
static void Main(string[] args)
{
Task.Run(Producer);
Task.Run(Consumer);
Console.ReadKey();
}
/// <param name="strDir">指定路径</param>
/// <param name="arrFiles">查询得到的所有文件名称ArrayList</param>
/// <param name="bIsRecursive">是否递归查询</param>
///
static string strDir = "D:\\";
static string[] imagePatterns = { "*.jpg", "*.jpeg", "*.png", "*.bmp","*.gif"};
public static void Producer()
{
ProDirectory(strDir, imagePatterns, arrFiles,true);
}
private static void ProDirectory(string strDir, string[] strFilePattern, string[] arrFiles, bool bIsRecursive)
{
if (string.IsNullOrEmpty(strDir))
{
return;
}
try
{
// 遍历所有文件模式
foreach (var pattern in strFilePattern)
{
// 尝试获取匹配的文件
string[] files = Directory.GetFiles(strDir, pattern);
foreach (var file in files)
{
unoccupied.Wait();
if (putin < Max)
{
arrFiles[putin] = file;
putin++;
occupied.Release();
}
}
}
if (bIsRecursive)
{ // 递归
string[] subDirs = Directory.GetDirectories(strDir);
foreach (string dir in subDirs)
{
ProDirectory(dir, strFilePattern, arrFiles, bIsRecursive);
}
}
}
catch
{// 异常处理
//Console.WriteLine("错误");
}
}
static string outputDirectory = @"E:\桌面\程序设计范式";
static Random random = new Random();
private static void Consumer()
{
while (true)
{
occupied.Wait();
if (putin > 0)
{
int index = takeout % Max;
string fileToProcess = arrFiles[index];
Console.WriteLine(fileToProcess);
AddWater(fileToProcess, outputDirectory);
arrFiles[index] = null; // 可以将已处理的文件设置为 null,以便垃圾回收
takeout++;
unoccupied.Release();
}
else
{
break;
}
}
}
private static void AddWater(string fileToProcess, string outputPath)
{
using (Image inImage = Image.FromFile(fileToProcess))
{
// 创建一个新的Bitmap对象,大小和原始图片一样
using (Bitmap bmp = new Bitmap(inImage.Width, inImage.Height))
{
// 初始化gdi绘图
using (Graphics graphics = Graphics.FromImage(bmp))
{
// 先将原始图片绘制到新的Bitmap上
graphics.DrawImage(inImage, new Point(0, 0));
// 设置水印字体、字号
Font font = new Font("Arial", 35, FontStyle.Italic, GraphicsUnit.Pixel);
// 设置水印颜色
Color color = Color.FromArgb(255, 233, 0, 0);
// 运算水印位置
Point atpoint = new Point(bmp.Width / 2, bmp.Height / 2);
// 初始化画刷
using (SolidBrush brush = new SolidBrush(color))
{
// 在Bitmap上绘制水印
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
graphics.DrawString("乌苏", font, brush, atpoint, sf);
}
// 创建一个随机文件名
string randomFileName = "Watermark_" + GenerateRandomNumber() + ".jpg";
// 构建完整路径
string fullPath = Path.Combine(outputPath, randomFileName);
// 保存图片到文件系统中
bmp.Save(fullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
}
private static string GenerateRandomNumber()
{
return random.Next(00001, 100000).ToString();
}
}