【问题标题】:Thread joblist management线程作业列表管理
【发布时间】:2016-05-31 09:51:35
【问题描述】:

我正在使用 C#。

我已经搜索了很长时间,但似乎找不到任何适合我的情况。这是我真正问题的摘要,因为它太复杂了,我无法解释。

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

你知道适合这种情况的任何例子吗?

【问题讨论】:

  • 单身模式适合吗?
  • 对并发没有帮助,我需要锁定列表并在打印后解锁它,但我不知道如何让它正常工作。
  • 您在寻找 ConcurrentList 吗?
  • 类似的东西,但更多关于如何使用它。

标签: c# multithreading list concurrency


【解决方案1】:

这些解决方案怎么样:

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();
}

【讨论】:

  • 该示例似乎只计算一个 int,然后等待输入,然后重复。但它需要不断计数,并且在随机点输入我的整数,然后通过打印机线程打印该输入。 1, 2, 3, 4, 1337, 5, 6, 7, 8, 9, 10 - 1337 是我的整数。
  • 亲爱的,BoinQ。我不清楚你需要什么。您能否尝试以其他方式解释或提供更多详细信息?
  • 我可以看到它非常接近。我有一个整数列表,这个列表需要与一个按整数读取整个列表整数的线程共享。还有一个线程,我可以在这个列表的前面输入新的整数。所以把我的“工作”放在列表中的其他“工作”之前。所以后台线程只是一个奴隶,它打印并删除列表中的第一个整数,直到它为空。当它为空时,它会等待打印更多整数。
  • 在我的示例中,如您所见,我使用的是 ConcurrentQueue (FIFO)。可以通过调用 Example.Add() 添加新的整数。 PrintMethod 正在等待输入,当有任何输入时,它开始从队列中读取所有项目。
  • 稍作修改后效果很好,非常感谢!
【解决方案2】:

效果很好。

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();
    }
}

【讨论】:

    猜你喜欢
    • 2010-10-08
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多