内存队列使用Channels

我也是copy别人的。

注册的主要方法体里面,我这是后台默默的处理日志。

var filechannel = Channel.CreateBounded<string>(6);

使用了有边界的,因为考虑到一次处理不完那么多。都放内存。内存会造反。

写一个生产者

public class Producer
{
private readonly ChannelWriter<string> _writer;
private readonly DirectoryInfo taskDir;
public Producer(ChannelWriter<string> writer)
{
_writer = writer;
taskDir = new DirectoryInfo(@"D:\logs");
}

public async Task CreateFileTask()
{
while (true)
{

var files = taskDir.GetFiles($"*.log").Where(q => q.CreationTime < DateTime.Now.AddSeconds(3))
.OrderBy(q => q.CreationTime).Take(100).ToList();
foreach (var filename in files)
{
if (await _writer.WaitToWriteAsync())
{

await _writer.WriteAsync(filename.FullName);
}
}
await Task.Delay(500);
}
}
}

 

消费者

public class Consumer
{
private readonly ChannelReader<string> _reader;
private string key;
public Consumer(ChannelReader<string> reader,string _key)
{
_reader = reader;
key = _key;
}

public async Task ConsumeData()
{

while (await _reader.WaitToReadAsync())
{
if (_reader.TryRead(out var filename))
{
if (!File.Exists(filename))
{
continue;
}

try
{
var text = File.ReadAllText(filename);
if (text.Length == 0)
{
File.Delete(filename);
continue;
}
Console.WriteLine($"{key}:{DateTime.Now}{filename}");
await Task.Delay(5000);
Console.WriteLine($"{key}:{DateTime.Now}{filename}");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
await Task.Delay(50000);
}
//await Task.Delay(500);
}
}
}
}

加入try,catch,是因为出错了。会停止。

主要的调用比如说在一个后台服务里面。

protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{

var filechannel = Channel.CreateBounded<string>(6);

var producer1 = new Producer(filechannel.Writer);
var consumer1 = new Consumer(filechannel.Reader,"0");
var consumer2 = new Consumer(filechannel.Reader,"1");
var consumer3 = new Consumer(filechannel.Reader,"2");

Task consumerTask1 = consumer1.ConsumeData(); // begin consuming
Task consumerTask2 = consumer2.ConsumeData(); // begin consuming
Task consumerTask3 = consumer3.ConsumeData(); // begin consuming

Task producerTask1 = producer1.CreateFileTask();

await producerTask1.ContinueWith(_ => filechannel.Writer.Complete());

await Task.WhenAll(consumerTask1, consumerTask2, consumerTask3);

}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
}
return Task.CompletedTask;
}

 

打完收工。水平很糙,主要是记录下。免得自己忘记。

posted @ 2021-01-27 16:43  forhells  阅读(179)  评论(0编辑  收藏  举报