2013-01-13 78 views
0

我正在研究一個應用程序,該應用程序在用戶可定製的時間間隔內生成多個線程,以便從{在此處插入任何類型的服務}檢索數據。我的應用程序使用CMD腳本(即生成Windows spawn conhost)並且有時會映射網絡驅動器,然後他們會按自定義的時間間隔休眠並重復。讓我們稱他們爲計數器。單獨同步兩個線程隊列並阻止執行?

到目前爲止好,但也有一些程序無法運行異步(映射驅動器,例如),所以我必須做出某種隊列爲一些特定線程使程序工作正常的。

到目前爲止,我已經能夠使用這裏找到的生產者/消費者隊列博客帖子來實現它 - >http://moazzam-khan.com/blog/?p=418。這在CMD計數器中工作,所以應用程序不會產生像7821678321 conhosts並阻止PC,我正在排隊它們。無論如何,這不是我遇到的問題。

當我需要映射網絡驅動器來運行某些命令並取消映射時,會出現問題,然後讓下一個線程執行。讓我更清楚地說明問題:

線程類型A:只需要排隊(只有A型),不需要等待B型線程執行或完成其執行。這實際上是通過本教程中的代碼完成的。

線程類型B:其他B型線程需要等待當前B型線程完成其執行。

我在考慮爲B型線程使用相同的教程,但我意識到我不能使用它,因爲其他線程保持調用自己直到它被解鎖,並且調用自己會重新映射驅動器, t工作(阿格,我可以看到,如果驅動器映射,但不是它映射到哪裏...我可以,但它是不想要的代碼,我想避免寫)。

我做了我的功課,並通過谷歌,甚至做了一個小應用程序,嘗試通過使用C#中的鎖關鍵字,但沒有成功,即使該功能阻止其他線程,他們仍然呼籲阻止功能,我不't想要那個:(

有很多的教程,但沒有一個是簡潔和足夠讓我瞭解他們。我在這裏發現了幾個問題,但他們大多是Java我在C#4.0中工作

嗯,這是我寫的代碼,如果你運行它,你會注意到其他線程會調用阻塞函數,我不希望函數是直到第一個線程w這叫它完成。要麼是這樣,要麼做某種類型的隊列,但也要避免由於其他線程執行其進程所需的時間而使隊列填滿。

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的執行和內存。

+0

你考慮BlockingCollection? – Paparazzi

+0

我做過了,但正如我在帖子中所說的,我正在使用C#4.0。那些新的集合是4.5,並在工作中,他們不希望我們實現VS2012呢:/ – DARKGuy

+0

我想我已經解決了它。我用一些谷歌搜索做的示例應用程序似乎可以工作。我會試試真正的應用程序並回報:) – DARKGuy

回答

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