C# 为什么这些次线程不结束它们的执行?
我正在创建一个控制台应用程序,它应该接收来自网络的消息,以便处理它们。首先,我创建了一个单例类,以确保所有类都可以访问相同的队列:这个类是C# 为什么这些次线程不结束它们的执行?,c#,.net,multithreading,thread-safety,C#,.net,Multithreading,Thread Safety,我正在创建一个控制台应用程序,它应该接收来自网络的消息,以便处理它们。首先,我创建了一个单例类,以确保所有类都可以访问相同的队列:这个类是ProcessingQueue public class ProcessingQueue { public class ItemToProcess { public string SourceClientId { get; set; } public IMessage ReceivedMessage { get;
ProcessingQueue
public class ProcessingQueue
{
public class ItemToProcess
{
public string SourceClientId { get; set; }
public IMessage ReceivedMessage { get; set; }
}
private int m_MaxSize = 20;
private Queue<ItemToProcess> m_InternalQueue;
private static volatile ProcessingQueue m_Instance = null;
private static readonly object syncRoot = new object();
private ProcessingQueue()
{
m_InternalQueue = new Queue<ItemToProcess>();
}
public static ProcessingQueue Instance
{
get
{
if (m_Instance == null)
{
lock (syncRoot)
{
if (m_Instance == null)
{
m_Instance = new ProcessingQueue();
}
}
}
return m_Instance;
}
}
public int MaxSize
{
get
{
lock (syncRoot)
{
return m_MaxSize;
}
}
set
{
if (value > 0)
{
lock (syncRoot)
{
m_MaxSize = value;
}
}
}
}
public void Enqueue(String source, IMessage message)
{
lock (syncRoot)
{
while (m_InternalQueue.Count >= m_MaxSize)
{
Monitor.Wait(syncRoot);
}
m_InternalQueue.Enqueue(new ItemToProcess { SourceClientId = source, ReceivedMessage = message });
if (m_InternalQueue.Count == 1)
{
Monitor.PulseAll(syncRoot);
}
}
}
public ItemToProcess Dequeue()
{
lock (syncRoot)
{
while (m_InternalQueue.Count == 0)
{
Monitor.Wait(syncRoot);
}
ItemToProcess item = m_InternalQueue.Dequeue();
if (m_InternalQueue.Count == m_MaxSize - 1)
{
Monitor.PulseAll(syncRoot);
}
return item;
}
}
public int Count
{
get
{
lock (syncRoot)
{
return m_InternalQueue.Count;
}
}
}
}
}
在执行过程中按Enter键,running
变量变为false,两个线程都应该终止。然而,这并不总是发生,事实上,两个方法Join
中的一个没有返回控件:因此,我在Join
方法中指定了一个超时,但在Console.WriteLine(“END”)之后
控制台应用程序冻结(第二个连接
返回假
)
可能第二个线程没有正确终止。。。为什么?似乎出列或排队可以进入
监视器。Wait()
,当停止运行时,没有人脉冲
等待5秒,但请注意MaxSize*1500>5000
我无法直接找出计时器的频率 使用
Lazy
实现单例模式要容易得多,但我一直认为单例模式是最粗糙的模式。好的,但我需要一个WCF服务实例可以访问的队列:在我的代码中,我模拟了来自网络的数据,但实际上,WCF服务的许多实例必须将数据放入队列中。我可以只更改Join
方法中的等待时间吗?或者我也应该使用更简单的方法而不是监视器
?您的入/出队列方法根本没有停止逻辑。。。只需使用一个library类。你所说的library类是什么意思?我应该使用类作为ConcurrentQueue
?
private static volatile bool running = true;
static void Main(string[] args)
{
queue.MaxSize = 30;
keep_alive_timer.Elapsed += new ElapsedEventHandler(delegate(object sender, ElapsedEventArgs e)
{
KeepAliveMessage msg = new KeepAliveMessage(Guid.NewGuid());
Console.WriteLine("Keep Alive: " + msg.MsgId);
queue.Enqueue("", msg);
});
keep_alive_timer.Enabled = true;
keep_alive_timer.AutoReset = true;
Thread processing = new Thread(delegate()
{
while (running)
{
Console.WriteLine("Number of elements in queue: {0}", queue.Count);
ProcessingQueue.ItemToProcess msg = queue.Dequeue();
Console.WriteLine("Processed: msgid={0}, source={1};", msg.ReceivedMessage.MsgId, msg.SourceClientId);
Thread.Sleep(1500);
}
});
Thread generating = new Thread(MessagesFromNetwork);
processing.Start();
keep_alive_timer.Start();
generating.Start();
Console.WriteLine("RUNNING...\n");
Console.ReadLine();
running = false;
keep_alive_timer.Stop();
Console.WriteLine("CLOSING...\n");
//processing.Abort();
//generating.Abort();
bool b1 = processing.Join(TimeSpan.FromSeconds(5));
bool b2 = generating.Join(TimeSpan.FromSeconds(5));
Console.WriteLine("b1 {0}", b1);
Console.WriteLine("b2 {0}", b2);
Console.WriteLine("END");
Console.ReadLine();
}
static void MessagesFromNetwork()
{
string[] sourceClients = { "1", "2", "3", "4", "5" };
while (running)
{
IMessage msg; // interface IMessage
Random random = new Random();
int type = random.Next(2);
switch (type)
{
case 0:
msg = new KeepAliveMessage(Guid.NewGuid()); // implements IMessage
break;
case 1:
msg = new TaskMessage(Guid.NewGuid(), ...); // implements IMessage
break;
default:
throw new Exception("Messaggio non valido!");
}
Console.WriteLine("New message received: " + msg.MsgId);
queue.Enqueue(sourceClients[random.Next(sourceClients.Length)], msg);
Console.WriteLine("... message enqueued: " + msg.MsgId);
Thread.Sleep(500);
}
}