作者addbear (无家的小孩)
看板C_Sharp
标题[问题] thread同步问题
时间Fri Dec 16 10:49:56 2011
各位先进打扰了:
最近在学习 C# 的 thread 使用方法,
目前是参考 msdn 上的 producer / consumer 范例来修改
http://msdn.microsoft.com/zh-tw/library/yy12yx1f(v=VS.80).aspx
以下是我修改後的程式码:
=========================================================
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
public class SyncEvents
{
public SyncEvents()
{
_newItemEvent = new AutoResetEvent(false);
_exitThreadEvent = new ManualResetEvent(false);
_eventArray = new WaitHandle[2];
_eventArray[0] = _newItemEvent;
_eventArray[1] = _exitThreadEvent;
}
public EventWaitHandle ExitThreadEvent
{
get { return _exitThreadEvent; }
}
public EventWaitHandle NewItemEvent
{
get { return _newItemEvent; }
}
public WaitHandle[] EventArray
{
get { return _eventArray; }
}
private EventWaitHandle _newItemEvent;
private EventWaitHandle _exitThreadEvent;
private WaitHandle[] _eventArray;
}
public class Producer
{
public Producer(ref Queue<int> q, ref SyncEvents e)
{
_queue = q;
_syncEvents = e;
}
public void ThreadRun()
{
int count = 0;
Random r = new Random();
while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
//while ((WaitHandle.WaitAny(_syncEvents.EventArray)) != 1)//queue为空
{
lock (((ICollection)_queue).SyncRoot)
{
count++;
_queue.Enqueue(count);
_syncEvents.NewItemEvent.Set();
Thread.Sleep(10);
}
}
Console.WriteLine("Producer thread: produced {0} items", count);
}
private Queue<int> _queue;
private SyncEvents _syncEvents;
}
public class Consumer
{
public Consumer(ref Queue<int> q, ref SyncEvents e)
{
_queue = q;
_syncEvents = e;
}
public void ThreadRun()
{
int count = 0;
while ( (WaitHandle.WaitAny(_syncEvents.EventArray)) != 1)
//while (!_syncEvents.ExitThreadEvent.WaitOne(0, false)) //会当掉
{
lock (((ICollection)_queue).SyncRoot)
{
int item = _queue.Dequeue();
Thread.Sleep(10);
}
count++;
}
Console.WriteLine("Consumer Thread: consumed {0} items", count);
}
private Queue<int> _queue;
private SyncEvents _syncEvents;
}
public class ThreadSyncSample
{
private static void ShowQueueContents(ref Queue<int> q)
{
// 这里为何只有 look ???
lock (((ICollection)q).SyncRoot)
{
Console.WriteLine("{0} ", q.Count);
}
}
static void Main()
{
// 设定二个要给 thread 用的共用资料结构
Queue<int> queue = new Queue<int>();
SyncEvents syncEvents = new SyncEvents();
// 建构 producer/consumer
Console.WriteLine("Configuring worker threads...");
Producer producer = new Producer(ref queue, ref syncEvents);
Consumer consumer = new Consumer(ref queue, ref syncEvents);
// 令 producer/consumer 的ThreadRun 可在 thread 中运行
Thread producerThread = new Thread(producer.ThreadRun);
Thread consumerThread = new Thread(consumer.ThreadRun);
// 令 二个 thread 中启动
Console.WriteLine("Launching producer and consumer threads...");
producerThread.Start();
consumerThread.Start();
// 显示 queue 中的内容
for (int i = 0; i < 4; i++)
{
Thread.Sleep(2500);
ShowQueueContents(ref queue);
}
// 下指令让 thread 可以离开
Console.WriteLine("Signaling threads to terminate...");
syncEvents.ExitThreadEvent.Set();
// 等待 thread 关闭
producerThread.Join();
consumerThread.Join();
}
}
========================================================
基本上我是希望 producer 产生一个数值放到 queue 并送出一个讯号後,
然後 consumer 则会从 queue 中消除刚才产生的数值,
之後,producer 则会因为收到讯号而再产生一个新数值,
让 queue 的内容不是放1个就是放0个,
但是这样改的结果却是 queue 所存的个数一直在上升中,
是谁发讯号给 producer 呢?不是只有当 consumer 处理完才由 consumer 送出的吗?
另一个问题则是 while 的功能应该是在判定是否有发出 _exitThreadEvent 吗?
为何互换後会产生问题呢?
谢谢
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.109.23.55