0
我搞亂了多線程和製作某種任務引擎。這個想法是,引擎可以有一個可配置數量的線程在等待,當一個新任務到達時,第一個空閒線程將其拾取並執行。c#多個線程等待一個ManualResetEvent
問題是某些2線程以某種方式獲取相同的任務。我查看了一下,我認爲這段代碼應該可以工作,但顯然不適用。如果我現在將其註釋掉了10ms的睡眠時間,那麼它可以工作,但我不確定我是否理解了原因。它看起來像.Reset()函數在實際重置事件之前返回?
有人可以解釋一下嗎?有沒有更好的方法讓只有一個線程在有多個等待時繼續?
由於
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskTest
{
public class Engine
{
private ManualResetEvent taskEvent;
private ConcurrentQueue<Task> tasks;
private bool running;
private List<Thread> threads;
private int threadAmount;
private int threadsBusy = 0;
public Engine(int amountOfThreads)
{
taskEvent = new ManualResetEvent(false);
tasks = new ConcurrentQueue<Task>();
threads = new List<Thread>();
threadAmount = amountOfThreads;
}
public void Start()
{
running = true;
for (var i = 0; i < threadAmount; i++)
{
var thread = new Thread(Process);
thread.Name = "Thread " + i;
threads.Add(thread);
thread.Start();
}
}
public void Stop()
{
running = false;
taskEvent.Set();
threads.ForEach(t => t.Join());
}
private void Process()
{
while (running)
{
lock (taskEvent)
{
// Lock it so only a single thread is waiting on the event at the same time
taskEvent.WaitOne();
taskEvent.Reset();
//Thread.Sleep(10);
}
if (!running)
{
taskEvent.Set();
return;
}
threadsBusy += 1;
if (threadsBusy > 1)
Console.WriteLine("Failed");
Task task;
if (tasks.TryDequeue(out task))
task.Execute();
threadsBusy -= 1;
}
}
public void Enqueue(Task t)
{
tasks.Enqueue(t);
taskEvent.Set();
}
}
}
EDIT 休息的代碼:
namespace TaskTest
{
public class Start
{
public static void Main(params string[] args)
{
var engine = new Engine(4);
engine.Start();
while (true)
{
Console.Read();
engine.Enqueue(new Task());
}
}
}
}
namespace TaskTest
{
public class Task
{
public void Execute()
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}
你想鎖定(OBJ)? – farmer1992
我不確定你的意思? –
這並不直接回答你的問題,但你應該改用BlockingCollection。它已經在做你正在做的事情,除了它可以工作 –