单独同步两个线程队列和块执行?

时间:2013-01-13 01:42:21

标签: c# .net multithreading queue blocking

我正在开发一个应用程序,它可以在用户自定义的时间间隔内生成多个线程,以便从{在此处插入任何类型的服务}中检索数据。我的应用程序使用CMD脚本(即使Windows生成conhost),有时映射网络驱动器,然后他们睡眠自定义间隔并重复。我们称他们为专柜​​。

到目前为止一直很好,但有一些程序不能异步运行(例如映射驱动器),所以我必须为某些特定线程创建某种队列,以便程序工作正常。

到目前为止,我已经能够使用此处的生产者/消费者队列博客文章实现它 - > http://moazzam-khan.com/blog/?p=418。这适用于CMD计数器,因此应用程序不会产生像7821678321 conhosts并阻止PC,我正在排队。无论如何,这不是我遇到的问题。

当我需要映射网络驱动器以运行某些命令并取消映射它然后让下一个线程执行时出现问题。让我更清楚地说明问题:

线程类型A :只需要排队(只有A类型),无需等待B类线程执行或完成执行。这实际上是使用教程中的代码完成的。

线程类型B :其他B类线程需要等待当前的B类线程才能完成执行。

我正在考虑为B型线程使用相同的教程,但我意识到我不能使用它,因为其他线程一直调用它们直到它被解除阻塞,并且调用它们会重新映射驱动器而它不会工作(唉,我可以看看驱动器是否被映射,但它映射到哪里......我可以,但这是我想避免写的不必要的代码。)

我完成了我的作业并通过谷歌甚至制作了一个小应用程序,通过在C#中使用lock关键字来尝试我的练习,但没有成功,即使该功能阻止其他线程,他们仍然调用阻塞功能而且我不会我想要:(

那里有很多教程,但没有一个是简明扼要的,足以让我理解它们。我在SO中找到了一些问题,但它们主要与java有关,我在C#4.0工作。

嗯,这是我写的代码。如果你运行它,你会注意到其他线程将调用阻塞函数。我不希望在调用它的第一个线程完成之前调用该函数。要么是这样,要么制作某种队列,但也要避免队列填充自己,因为其他线程在完成他们的过程时所花费的时间。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ThreadTest
{
    public class BlockObj
    {
        Object lockObj = new Object();

        public void DoBlock(int id)
        {
            lock (lockObj)
            {
                Console.WriteLine("Counter " + id + " locking object created, wait 5 sec");
                Thread.Sleep(5000);
                Console.WriteLine("Stuff done, keep going");
            }
        }
    }

    class Program
    {
        static Random r = new Random(DateTime.Now.Second);
        static BlockObj oo = new BlockObj();

        public static void Counter(object id)
        {
            int i = (int)id;
            while (true)
            {
                Thread.Sleep(1000 * r.Next(1, 10));
                Console.WriteLine("Counter " + i + " call blocking stuff...");
                oo.DoBlock(i);
                Console.WriteLine("Counter " + i + " finish work");
            }
        }

        public static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(Counter));
                t.Start(i);
            }
        }
    }
}

实际上,我希望看到一个应用程序的概念验证代码可以产生两个线程队列,并且这些队列中的线程将等待当前线程在运行下一个线程之前完成执行。但是,每个队列都有自己的阻塞。线程队列1不应该阻止线程队列2执行和visceversa。

1 个答案:

答案 0 :(得分:0)

好吧,我刚用自己的代码解决了这个问题,尝试了一些东西直到它起作用了。)。

对于那些想要同步的简单队列的人来说,这里是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections;
using System.Runtime.Remoting.Messaging;

namespace TheadingPool1
{
    // http://www.c-sharpcorner.com/UploadFile/mgold/QueueInThread11222005232529PM/QueueInThread.aspx

    public class ThreadQueue
    {
        private Queue _qOrder = new Queue();
        private Queue _qSync;
        private Thread _qThread;
        private ManualResetEvent _eWait = new ManualResetEvent(false);

        private int _wait;

        public ThreadQueue(int w)
        {
            _wait = w;
            _qSync = Queue.Synchronized(_qOrder);
        }

        public void Start()
        {
            _qThread = new Thread(new ThreadStart(Process));
            _qThread.IsBackground = true;
            _qThread.Start();
        }

        public void Process()
        {
            Random x = new Random(DateTime.Now.Second);
            object item;
            while (true)
            {
                item = null;
                lock (_qSync.SyncRoot)
                {
                    if (_qSync.Count > 0)
                    {
                        item = (object)_qSync.Dequeue();
                    }
                    else
                    {
                        _eWait.Reset();
                    }
                }
                if (item != null)
                {
                    Console.WriteLine("[" + _wait + "] [" + item.ToString() + "] :D");
                    Thread.Sleep(_wait * x.Next(1, 5));
                }
                else
                {
                    _eWait.WaitOne();
                }
            }
        }

        public void Enqueue(object obj)
        {
            _qSync.Enqueue(obj);
            _eWait.Set();
        }
    }

    public class Program
    {
        private static ThreadQueue _q1 = new ThreadQueue(10);
        private static ThreadQueue _q2 = new ThreadQueue(50);

        public static void Main(string[] args)
        {
            _q1.Start();
            _q2.Start();

            for (int i = 0; i < 50; i++)
                _q1.Enqueue(i);

            for (int i = 0; i < 50; i++)
                _q2.Enqueue(i);

            while (true)
            {
                Thread.Sleep(100);
            }
        }
    }
}