2011-05-18 24 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

相关问题