假设我有一个列表,并且将数据从命名管道传输到该列表。
假设样本:
private void myStreamingThread()
{
while(mypipe.isconnected)
{
if (mypipe.hasdata)
myList.add(mypipe.data);
}
}
然后在另一个线程上,我需要每1000ms读取一次该列表,例如:
private void myListReadingThread()
{
while(isStarted)
{
if (myList.count > 0)
{
//do whatever I need to.
}
Thread.Sleep(1000);
}
}
我的优先事项是能够每1000毫秒读取一次列表,并根据列表执行我需要的任何操作,但同时能够从管道获取新数据非常重要。
有什么好方法可以解决这个问题?
忘记提及我与.NET 3.5绑定
答案 0 :(得分:2)
我建议使用Queue锁定。
Queue<string> myQueue = new Queue<string>();
private void myStreamingThread()
{
while(mypipe.isconnected)
{
if (mypipe.hasdata)
{
lock (myQueue)
{
myQueue.add(mypipe.data);
}
}
}
}
如果要每1000毫秒清空一次队列,请不要使用Thread.Sleep
。请改用timer。
System.Threading.Timer t = new Timer(myListReadingProc, null, 1000, 1000);
private void myListReadingProc(object s)
{
while (myQueue.Count > 0)
{
lock (myQueue)
{
string item = myQueue.Dequeue();
// do whatever
}
}
}
请注意,上面假设该队列仅由一个线程读取。如果多个线程正在读取,则存在竞争条件。但上述内容适用于单个读者和一个或多个作者。
答案 1 :(得分:1)
我建议使用ConcurrentQueue(http://msdn.microsoft.com/en-us/library/dd267265.aspx)。如果您使用简单的列表&lt;&gt;然后你会鼓励很多线程问题。
另一种做法是使用名为outstandingWork的互斥锁并等待它而不是Thread.Sleep()。然后,当你排队一些工作时,你就会出类拔萃的工作。这意味着当没有工作可用时你会睡觉但是立即开始处理工作而不是整整1秒睡眠。
修改强>
正如@Prix指出的那样,您正在使用.Net 3.5。所以你不能使用ConcurrentQueue。使用带有以下
的Queue类Queue<Work> queue;
AutoResetEvent outstandingWork = new AutoResetEvent(false);
void Enqueue(Work work)
{
lock (queue)
{
queue.Enqueue(work);
outstandingWork.Set();
}
}
Work DequeMaybe()
{
lock (queue)
{
if (queue.Count == 0) return null;
return queue.Dequeue();
}
}
void DoWork()
{
while (true)
{
Work work = DequeMaybe();
if (work == null)
{
outstandingWork.WaitOne();
continue;
}
// Do the work.
}
}