2011-05-18 22 views
3

我有下面的代碼來處理。我在這裏遇到的問題是,代碼在while循環中運行,無需等待線路上的輸入String temp = Console.ReadLine()。需要幫助瞭解爲什麼以及如何解決請。提前致謝!爲什麼Console.Readline沒有按預期執行

/*Banker's algorithm Implementation*/ 
    class Program 
    { 

     static void Main(string[] args) 
     { 
       int n = 0;//number of resources we will be dealing with 
       int proc_num = 0;//Total number of processes to share available resources 

       IDictionary<String, SysProcess> processes = new Dictionary<String, SysProcess>(); 
       IDictionary<String, int> MaxR = new Dictionary<String, int>();// maximum available resources 
       IDictionary<String, int> avail = new Dictionary<String, int>();// Available resources after first allocation 
       Dictionary<String, int> availsum = new Dictionary<string, int>(); 

       //Start 
       while (true) 
       { 
        Console.WriteLine(" What is number of resources to be shared? : "); 
          if (!int.TryParse(Console.ReadLine(), out n)) 
          { 
           Console.WriteLine(" Error Please provide valid number --- {0}!", n); 
          } 
          else 
          { 
           break; 
          } 
       } 

       //get the maximum number of each Resources Ie Total Resources Available 
       while (true && n>0) 
       { 
        Console.WriteLine("Using a comma delimited list(e.g. 0, 0, 0, 0) list maximum of each of the {0} resources : ", n); 
        String temp; 
         temp = Console.ReadLine(); 

        if (!String.IsNullOrEmpty(temp)) 
        { 
          String[] maxR = temp.Split(','); 
          for (int a = 1; a <= n; a++) 
          { 
           MaxR.Add("Resource#" + a.ToString(), Convert.ToInt32(maxR[a])); 
          } 
          break; 
        } 
       } 


       while (true && n>0) 
       { 
        Console.Write("Enter total number of processes to share the available resources :"); 
        if (!int.TryParse(Console.Read().ToString(), out proc_num)) 
        { 
          Console.WriteLine(" Error Please provide valid number --- {0}!", proc_num); 
        } 
        else 
        { break; } 
       } 

       if(proc_num > 0) 
       { 
        //Request Process Max and allocated resources data 
        for (int i = 1; i <= proc_num; i++) 
        { 
          Console.Write("Using a comma delimited list, Enter total number of Resources 1 through {0} are needed by PROCESS#{1} ?", n, i); 
          String[] temps = Console.ReadLine().Split(','); 
          SysProcess tempproc = new SysProcess("Process#" + i.ToString()); 

          for (int a = 0; a < temps.Length; a++) 
          { 
           tempproc.Add_max_resource("Resource#" + (a + 1).ToString(), Convert.ToInt32(temps[a])); 
          } 

          //How many resources have already been allocated to each resource 
          temps = null; 
          Console.Write("Using a comma delimited list,Enter number of resources 1 through {0} already allocated to PROCESS#{1} ? ", n, i); 
          temps = Console.ReadLine().Split(','); 
          for (int a = 0; a < temps.Length; a++) 
          { 
           tempproc.add_alloc_resource("Resource#" + (a + 1).ToString(), Convert.ToInt32(temps[a])); 
          } 
          processes.Add("Process#" + i.ToString(), tempproc); 
        } 


        Console.WriteLine("Processing . . . "); 
        Console.WriteLine(); 
        Console.WriteLine("Available resources "); 

        //Compute Available Resources 
        for (int i = 0; i < n; i++) 
        { 
          if (!availsum.ContainsKey("Resource#" + (i + 1).ToString())) 
           availsum.Add("Resource#" + (i + 1).ToString(), 0); 
          foreach (SysProcess sp in processes.Values) 
          {  //add sum up the available 
           availsum["Resource#" + (i + 1).ToString()] += sp.alloc_resources["Resource#" + (i + 1).ToString()]; 
          } 
        } 

        //print out the availables we computed 

        Console.Write(" avail< "); 
        for (int j = 0; j < n; j++) 
        { 

          Console.Write(availsum["Resource#" + (j + 1).ToString()] + ","); 

          if (j + 1 == n)//if this is the last one, go ahead and output the rest 
           Console.Write("{0} > ", availsum["Resource#" + (j + 1).ToString()]); 
        } 


        // Printing resources still needed 
        Console.WriteLine(); 
        foreach (SysProcess p in processes.Values) 
        { 
          p.print_needed(); 
        } 


        //a) Find a row in the Need matrix which is less than the Available vector. 
        //If such a row exists, then the process represented by that row may complete 
        //with those additional resources. If no such row exists, eventual deadlock is possible. 
        Dictionary<String, int> _currentavailsum; 

        foreach (SysProcess p in processes.Values) 
        { 
          int TotalSproccounter = 0; 
          String safelead; 
          if (isprocessSafe(n, p, availsum)) 
          { 
           TotalSproccounter++; 
           safelead = p.id; 
           _currentavailsum = new Dictionary<String, int>(); 
           _currentavailsum = availsum;//get a copy of the original data to begin with 
           foreach (SysProcess q in processes.Values) 
           { 
             if (q != p)//we only want to compare with the others from here 
             { 
              if (isprocessSafe(n, p, _currentavailsum)) 
              { 
                update_availsum(n, q, ref _currentavailsum);//update the currentavail count 
                TotalSproccounter++; 
                //update print 
                safelead += ", " + q.id; 
              } 
             } 
           } 

           if (TotalSproccounter == proc_num) 
           { 
             Console.WriteLine("Safe allocation < {0} >", safelead); 
           } 
           else 
           { 
             Console.WriteLine("Deadlock reached/unsafe allocation : < {0} >", safelead); 
           } 
          } 
        } 
       } 
       Console.ReadLine(); 
     } 

     //compares the number of resources needed against the number of resources available 
     public static Boolean isprocessSafe(int n, SysProcess p, IDictionary<String, int> avail) 
     { 
       int safecount = 0; 
       foreach (String resourcekey in avail.Keys) 
       { 
        if (p.need_resources.ContainsKey(resourcekey) && p.need_resources[resourcekey] <= avail[resourcekey]) 
        { 
          safecount++; 
        } 

       } 
       if (safecount == n) 
       { 

        return true; 
       } 
       return false; 
     } 

     //compares the number of resources needed against the number of resources available 
     public static void update_availsum(int n, SysProcess p, ref Dictionary<String, int> _currentavailsum) 
     { 
       foreach (String resourcekey in _currentavailsum.Keys) 
       { 
        if (p.need_resources.ContainsKey(resourcekey)) 
        { 
          _currentavailsum[resourcekey] += p.need_resources[resourcekey]; 
        } 

       } 
     } 

    } 

    //container class for processes 
    public class SysProcess 
    { 
     public String id { get; set; } 
     Dictionary<String, int> _max_resources = null; // will hold the Resource name and the the number of resources 
     Dictionary<String, int> _alloc_resources = null;//allocated resources 
     Dictionary<String, int> _need_resources = null;//allocated resources 

     public Dictionary<String, int> max_resources 
     { 
       get 
       { return _max_resources; } 

     } 

     public Dictionary<String, int> alloc_resources 
     { 
       get 
       { 
        return _alloc_resources; 

       } 
     } 

     public Dictionary<String, int> need_resources 
     { 
       get 
       { 
        return _need_resources; 

       } 
     } 

     public SysProcess(String procID) 
     { 
       _max_resources = new Dictionary<String, int>(); 
       _alloc_resources = new Dictionary<String, int>(); 
       id = procID; 
     } 

     public void Add_max_resource(String resource, int count) 
     { 
       _max_resources.Add(resource, count); 
     } 

     public void add_alloc_resource(String resource, int count) 
     { 
       _alloc_resources.Add(resource, count); 
       _need_resources.Add(resource, _max_resources[resource] - alloc_resources[resource]); 
     } 

     public void print_needed() 
     { 
       Console.Write(id); 
       foreach (int s in _need_resources.Values) 
       { 
        Console.Write(" {0}", s); 
       } 

     } 
    } 

在這裏添加整個代碼可能是一個好主意,因爲我仍然無法解決這個問題。請幫助

+0

您的循環條件是多餘的:IsNullOrWhiteSpace()將覆蓋IsNullOrEmpty()涵蓋的所有情況。非挑剔的問題:你如何提供應用程序的輸入?你是從另一個應用程序傳送數據,還是將文件傳送給它? – dlev 2011-05-18 17:15:39

+0

什麼是n?此代碼應該正常工作並等待輸入 – 2011-05-18 17:19:14

+0

您確定項目輸出類型是「控制檯應用程序」嗎?這項工作是否在主線程上發生? – 2011-05-18 17:21:36

回答

5

問題是使用有問題的方法Console.Read()。該方法將阻塞,直到輸入完整的文本行,但它只返回第一個字符,剩下的文本留在輸入緩衝區中。當執行Console.ReadLine()操作時,用於輸入第一個值並取消阻止讀取操作的回車仍然位於輸入緩衝區中。因此,返回一個空行。

我建議您用Console.ReadLine()替換Console.Read().ToString()來解決這個問題。

的問題可以用這個代碼來證明:

static void Main(string[] args) 
    { 
     string value = Console.Read().ToString(); 
     Console.WriteLine("You entered: {0}", value); 
     Console.WriteLine("Press ENTER to continue..."); 
     Console.ReadLine(); // Returns immediately. 
     Console.WriteLine("Continuing...."); 
    } 

固定這樣的:

 string value = Console.ReadLine(); 
+0

謝謝,原來是這個問題。只要我切換到使用Console.ReadLine(),問題就消失了。 – Kobojunkie 2011-05-18 22:00:42

0

您的輸入中可能有重複的/額外的換行符。此代碼看起來非常適合解析逗號分隔的文件...

+0

我剛剛發佈了所有代碼,供您參閱。那裏我沒有任何額外的線路。 – Kobojunkie 2011-05-18 21:18:08

2

您的項目是否配置爲控制檯應用程序?它需要使用不同的開關構建,以便在exe文件中設置標誌,以便OS加載程序知道它需要爲該進程創建控制檯窗口。 GUI應用程序不會設置該標誌,也不會獲得控制檯窗口。

在VS2010中,右鍵單擊項目的屬性鏈接,單擊應用程序選項卡,然後將輸出類型從Windows應用程序更改爲控制檯應用程序。重建並運行。

+1

我沒有想到的好點。我只是檢查和Console.ReadLine()將立即返回,如果該項目不是一個控制檯項目。 – 2011-05-18 17:25:41

+2

這是我一直都在做的一件事。 :P – dthorpe 2011-05-18 17:28:53

+0

剛剛選中,輸出類型已經設置爲控制檯應用程序。 – Kobojunkie 2011-05-18 17:53:55

0

問題可能是您正試圖從控制檯讀取的輸入流中的東西。如果您不想擔心緩衝區中已存在的內容,則可以嘗試對其進行刷新,以便從全新的空輸入狀態開始。不速之客,所有Console.Read *功能似乎都是阻塞功能。但是,還有KeyAvailable屬性,用於指示是否有可用的內容。

這提供了以下代碼:

private void clearInputBuffer() 
{ 
    while(Console.KeyAvailable) 
    { 
     Console.Read(); // read next key, but discard 
    } 
} 

或者,對於輸入緩衝器,在基層中,流。一個TextReader,具體。這可從

Console.In 

所以,你可以使用的功能有,如.ReadToEnd(),以清除你在一段時間(true)循環進入權前的緩衝區。

+0

我試過上面的解決方案,但它似乎沒有改變任何東西。在運行過程中逐步完成代碼,我發現確實沒有數據被帶回。 – Kobojunkie 2011-05-18 21:19:03

0

的問題是,你曲解什麼Console.Read一樣。它從輸入流中讀取下一個字符並將其作爲整數返回。但是......這裏是很好的一部分,除非你按Enter鍵,否則什麼都不會進入。所以如果你在第一個提示符下輸入「abc」,然後按下Enter鍵,你將從緩衝區獲取第一個字符,作爲整數(97)。但輸入緩衝區將包含「bc」和換行符,然後由Readline使用。

如果您需要Console的字符串,請撥打ReadLine而不是Read

相關問題