线程作业列表管理



我正在使用C#。

我已经寻找了很多年了,似乎找不到任何适合我的情况。这是我真正问题的摘要,因为它对我来说太复杂了,无法解释。

我有一个工作线程,每次打印后都会有很小的延迟从列表中打印整数,当打印整数时,它会从列表中删除,当列表为空时,它应该等待添加更多。现在我需要能够 - 在任何时候 - 将我选择的一些添加到此列表的前面。但是我遇到了并发问题。因为他们显然不能同时在名单上工作。我一直在研究生产者-消费者模式,但我无法让它适合这个项目。

你知道有什么适合这种情况的例子吗?

这些解决方案呢:

class Example
{
    private readonly ManualResetEventSlim _hasNewData;
    private readonly ConcurrentQueue<int> _queue;
    private readonly CancellationTokenSource _stopConsumers;
    private readonly ManualResetEvent _waitForStopping;
    private Task _printTask;
    public Example()
    {
        _hasNewData = new ManualResetEventSlim(false);
        _queue = new ConcurrentQueue<int>();
        _stopConsumers = new CancellationTokenSource();
        _waitForStopping = new ManualResetEvent(false);
    }
    public void Start()
    {
        _printTask = Task.Factory.StartNew(() => PrintMethod());
    }
    public void Add(int v)
    {
        _hasNewData.Set();
        _queue.Enqueue(v);
    }
    public void Stop()
    {
        _stopConsumers.Cancel();
        _waitForStopping.WaitOne();
    }
    private void PrintMethod()
    {
        while (!_stopConsumers.IsCancellationRequested)
        {
            _hasNewData.Wait();
            int v;
            while(_queue.TryDequeue(out v))
            {
                Console.WriteLine("Dequed: {0}", v);
            }
        }
        _waitForStopping.Set();
    }
}

以这种方式使用:

Example e = new Example();
e.Start();
int k = 0;
while (true)
{
    e.Add(k++);
    Console.ReadLine();
}

这非常有效。

class Program
{
    static void Main(string[] args)
    {
        int[] ints = new int[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110,120,130,140,150 };
        Example e = new Example();
        e.AddRange(ints);
        e.Start();
        int k = 0;
        while (true)
        {
            int input = int.Parse(Console.ReadLine());
            e.Add(input);
        }
    }
}
class Example
{
    private readonly ManualResetEventSlim _hasNewData;
    private readonly ConcurrentStack<int> _queue;
    private readonly CancellationTokenSource _stopConsumers;
    private readonly ManualResetEvent _waitForStopping;
    private Task _printTask;
    public Example()
    {
        _hasNewData = new ManualResetEventSlim(false);
        _queue = new ConcurrentStack<int>();
        _stopConsumers = new CancellationTokenSource();
        _waitForStopping = new ManualResetEvent(false);
    }
    public void Start()
    {
        _printTask = Task.Factory.StartNew(() => PrintMethod());
    }
    public void AddRange(int[] ints)
    {
        _hasNewData.Set();
        _queue.PushRange(ints);
    }
    public void Add(int v)
    {
        _hasNewData.Set();
        _queue.Push(v);
    }
    public void Stop()
    {
        _stopConsumers.Cancel();
        _waitForStopping.WaitOne();
    }
    private void PrintMethod()
    {
        while (!_stopConsumers.IsCancellationRequested)
        {
            _hasNewData.Wait();
            int v;
            while (_queue.TryPop(out v))
            {
                Console.WriteLine("Dequed: {0}", v);
                Thread.Sleep(500);
            }
        }
        _waitForStopping.Set();
    }
}

最新更新