1. 程式人生 > >(C#)使用佇列(Queue)解決簡單的併發問題

(C#)使用佇列(Queue)解決簡單的併發問題

有一個場景:一個搶購的專案,假設有5件商品,誰先搶到誰可以買,但是如果此時此刻(這裡的此時此刻假設是相同的時間),有100人去搶這個商品,如果使用平時的方法會出現什麼情況呢?你懂的,這裡所說是就是有關併發的問題。

平時我們去超市購物去結賬的時候就是排隊,這裡我們先讓搶購人排好隊,按時間,誰先點選的搶購按鈕誰就排在前面,這樣就形成了一個佇列,然後我們再對這個佇列處理,這樣就不會出現併發的問題了。(至少可以處理這樣簡單的併發,這裡不討論太複雜的併發)

案例:

要求:有一個釋出文章的介面,每釋出一篇文章,呼叫一下介面。(這裡不用批量釋出,為了講解這個)

建立一個這樣的處理程式類,BusinessInfoHelper.cs

namespace MyNameSpace 

{
    //佇列臨時類
    public class QueueInfo
    {
        public string medias { get; set; }
        public string proids { get; set; }
        public string host { get; set; }
        public string userid { get; set; }
        public string feedid { get; set; }
    }

    public class BusinessInfoHelper
    {
        #region 解決釋出時含有優質媒體時,前臺頁面卡住的現象
        //原理:利用生產者消費者模式進行入列出列操作

        public readonly static BusinessInfoHelper Instance = new BusinessInfoHelper();
        private BusinessInfoHelper()
        { }

        private Queue<QueueInfo> ListQueue = new Queue<QueueInfo>();

        public void AddQueue(string medias, string proids, string host, string userid, string feedid) //入列
        {
            QueueInfo queueinfo = new QueueInfo();

            queueinfo.medias = medias;
            queueinfo.proids = proids;
            queueinfo.host = host;
            queueinfo.userid = userid;
            queueinfo.feedid = feedid;
            ListQueue.Enqueue(queueinfo);
        }

        public void Start()//啟動
        {
            Thread thread = new Thread(threadStart);
            thread.IsBackground = true;
            thread.Start();
        }

        private void threadStart()
        {
            while (true)
            {
                if (ListQueue.Count > 0)
                {
                    try
                    {
                        ScanQueue();
                    }
                    catch (Exception ex)
                    {
                        LO_LogInfo.WLlog(ex.ToString());
                    }
                }
                else
                {
                    //沒有任務,休息3秒鐘
                    Thread.Sleep(3000);
                }
            }
        }

        //要執行的方法
        private void ScanQueue()
        {
            while (ListQueue.Count > 0)
            {
                try
                {
                    //從佇列中取出
                    QueueInfo queueinfo = ListQueue.Dequeue();

                    //取出的queueinfo就可以用了,裡面有你要的東西
                    //以下就是處理程式了
                    //。。。。。。

                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }


        #endregion
    }
}



以上頁面寫好後,在程式開始執行時就得啟動這個執行緒去不停的處理任務,那麼我們在Global的Application_Start裡可以這樣寫:

//啟動釋出優質媒體程式
MyNameSpace.BusinessInfoHelper.Instance.Start();


有一個問題出來了,如果我處理完佇列中的一條記錄後,想返回這條記錄的ID,這個程式好像不能完成,我就使用了另一個方法 Lock方法 ,把方法鎖定,具體的如下,

在頁面中定義全域性的鎖:

private static object lockObject= new Object();

在方法 中這樣呼叫:

lock(lockObject)

{

//........

}


如果不使用第二種方法的全域性鎖,不知各位大俠有沒有好的解決辦法,如果有,可以跟貼,非常感謝!