我的队列机制线程安全吗?我只是想知道我是否需要并发集合。我需要锁定入队方法吗?控制台以不正确的顺序显示队列计数,是否会影响Load方法中的maxQueueCount?我可以以某种方式进行改进吗?我希望队列具有最大大小,并且我不想再次将同一项目排队。
我有许多数据库源以及选择文档的存储过程。每个文档都有唯一的ID,但可能包含在许多数据源中。因此,我需要检查是否在我的数据流中处理了具有指定ID的文档。我不想阻塞我的队列,所以如果队列计数等于= 1000,我就不会排队新文档。
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Timers;
class Program
{
public class Document : IItem
{
public Guid Id { get; set; }
}
static void Main()
{
var queueProvider = new Provider();
var docs = new List<IItem>
{
new Document { Id = Guid.NewGuid() },
new Document { Id = Guid.NewGuid() },
new Document { Id = Guid.NewGuid() },
new Document { Id = Guid.NewGuid() },
new Document { Id = Guid.NewGuid() }
};
try
{
var tasks = new List<Task>();
var task1 = Task.Factory.StartNew(() =>
{
var timer1 = new Timer(1000) { Interval = 1000 };
timer1.Elapsed += (object sender, ElapsedEventArgs e) =>
{
queueProvider.Load(docs, 1);
};
timer1.Enabled = true;
timer1.Start();
});
tasks.Add(task1);
var task2 = Task.Factory.StartNew(() =>
{
var timer1 = new Timer(1000) { Interval = 1000 };
timer1.Elapsed += (object sender, ElapsedEventArgs e) =>
{
queueProvider.Load(docs, 2);
};
timer1.Enabled = true;
timer1.Start();
});
tasks.Add(task2);
//Dequeue
//var task3 = Task.Factory.StartNew(() =>
//{
// var timer1 = new Timer(3000) { Interval = 1000 };
// timer1.Elapsed += (object sender, ElapsedEventArgs e) =>
// {
// queueProvider.Dequeue();
// };
// timer1.Enabled = true;
// timer1.Start();
//});
//tasks.Add(task3);
Task.WaitAll(tasks.ToArray());
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
public interface IItem
{
Guid Id { get; set; }
}
public interface IProvider
{
void Enqueue(IItem feedingItem, int id);
}
public class Provider : IProvider
{
private readonly ConcurrentQueue<IItem> queue;
private readonly ConcurrentDictionary<Guid, DateTime> inputBuffor;
private readonly object locker = new object();
private int maxQueueCount = 3;
public Provider()
{
queue = new ConcurrentQueue<IItem>();
inputBuffor = new ConcurrentDictionary<Guid, DateTime>();
}
public IItem Dequeue()
{
queue.TryDequeue(out var item);
Console.WriteLine("Dequeue: " + item.Id);
return item;
}
public void Enqueue(IItem item, int id)
{
//lock (locker)
//{
if (inputBuffor.TryAdd(item.Id, DateTime.Now))
{
queue.Enqueue(item);
Console.WriteLine("Enqueue: " + item.Id + "taskId: " + id);
Console.WriteLine("Count: " + queue.Count + " Buffor: " + inputBuffor.Count);
}
else
{
Console.WriteLine("Not Enqueue: " + item.Id + "taskId: " + id);
}
//}
}
public void Load(IEnumerable<IItem> data, int id)
{
foreach (var item in data)
{
if (queue.Count < maxQueueCount)
Enqueue(item, id);
}
}
}
更新 我将Enqueu方法重命名为TryEnqueue,并添加了BlockingCollection而不是Concurent Collection。
var task1 = Task.Factory.StartNew(() =>
{
var timer1 = new Timer(1000) { Interval = 1000 };
timer1.Elapsed += (object sender, ElapsedEventArgs e) =>
{
foreach(var doc in docs)
{
if (queueProvider.TryEnqueue(doc, 1))
{
Console.WriteLine("Enqueue: " + doc.Id + "taskId: 2");
Console.WriteLine("Count: " + queueProvider.QueueCount + " Buffor: " + queueProvider.BufforCount);
}
else
{
Console.WriteLine("Not Enqueue: " + doc.Id + "taskId: 2");
}
}
};
timer1.Enabled = true;
timer1.Start();
});
tasks.Add(task1);
public bool TryEnqueue(IItem item, int id)
{
if (inputBuffor.TryAdd(item.Id, DateTime.Now))
{
if (queue.TryAdd(item))
{
return true;
}
}
return false;
}
public IItem Dequeue()
{
queue.TryTake(out var item);
return item;
}
答案 0 :(得分:1)
多个线程可以同时满足<Grid Grid.Row="0" Grid.Column="1" >
<!--Remove the RowDefinitions/ColumnDefinitions-->
<RichTextBox Name="txtLog">
<FlowDocument>
<Paragraph FontSize="12">Hello, world!</Paragraph>
</FlowDocument>
</RichTextBox>
</Grid>
,然后每个线程都将运行您的Enqueue方法并超过maxQueueCount。那绝对不是线程安全的。我会将其移至您的EnqueueMethod中,并用锁将其包围。