为什么while循环挂起 [英] Why while loop hangup

查看:159
本文介绍了为什么while循环挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




当我尝试转换文本文件时,它会超过2000行和挂断

你能解释一下原因吗?



提前致谢



Ajith



我是什么尝试过:



Hi
When I try converting text file it goes for over 2000 lines and hangup
can you explain why ?

Thanks in advance

Ajith

What I have tried:

DateTime datetime;

           OpenFileDialog choofdlog = new OpenFileDialog();
           choofdlog.Filter = "All Files (*.DAT)|*.DAT";
           choofdlog.FilterIndex = 1;
           choofdlog.Multiselect = true;
           string cToken;
           string cToken1;
           string cToken2;
           string cTime;
           string cDate;
           string cIdno;
           int nRecnt = 0;

           DataTable userdt = new DataTable();
           userdt = this.timeattDataSet.data  ;

           if (choofdlog.ShowDialog() == DialogResult.OK)
           {
               foreach (string sFileName in choofdlog.FileNames)
               {
                   using (FileStream fs = new FileStream(sFileName, FileMode.Open, FileAccess.Read))
                   {

                       StreamReader sr = new StreamReader(fs);

                       sr.BaseStream.Seek(0, SeekOrigin.Begin);

                       string str = sr.ReadLine();

                       while (str != null)

                       {

                           // Console.WriteLine(str);

                           str = sr.ReadLine();
                           if (str != null)
                           {
                               cToken1 = str.ToString().Substring(0, 9).Trim();
                               cToken2 = '5' + cToken1.PadLeft(5, '0');
                               cToken = cToken2.Substring(0, 6);
                               cDate = str.ToString().Substring(10, 10);
                               cTime = str.ToString().Substring(21, 2) + str.ToString().Substring(24, 2);
                               cIdno = str.ToString().Substring(30, 1);
                               datetime = System.Convert.ToDateTime(cDate);

                               nRecnt = nRecnt + 1;
                               this.textBox2.Text = nRecnt.ToString();
                               this.textBox2.Refresh();

                               string queryString = "Token_no = '" + cToken + "' AND Date = '" + datetime +"' AND Time ='" + cTime + "'";
                               bool rowExists = userdt.AsEnumerable().Any(row => string.Equals(row.Field<string>("Token_no"), cToken, StringComparison.OrdinalIgnoreCase) && row.Field<DateTime>("Date") == datetime && row.Field<string>("Time") == cTime);

                               if (rowExists == false)
                                   {
                                       this.textBox1.Text = cToken + '-'+ datetime;
                                       this.textBox1.Refresh();
                                       DataRow newCustomersRow = this.timeattDataSet.Tables["data"].NewRow();
                                       newCustomersRow["Token_no"] = cToken;
                                       newCustomersRow["Date"] = datetime;
                                       newCustomersRow["Time"] = cTime;
                                       newCustomersRow["Terminal"] = cIdno;
                                       newCustomersRow["Mode"] = "T";
                                       newCustomersRow["In_out"] = "";
                                       newCustomersRow["Updated"] = false;

                             }

                           }
                           else
                           {
                               break;
                           }
                       }

                       sr.Close();

                       fs.Close();

                   }
               }

           }

推荐答案

当您编写Windows应用程序时,它以一个线程开始 - 这意味着它可以一次执行一项操作。如果您正在忙于从文件中读取和处理行,那么在您完成此操作之前,您的应用程序将无法执行任何其他操作 - 包括不响应用户输入或更改显示的请求:因为Windows通过向当你的应用程序回到它的空闲循环并寻找要做的事情时它处理的应用程序。如果你一直忙于查看文件中的行,那么它永远不会用完所有事情,也从不查看它的消息集。



所以你需要开始第二个线程在幕后做所有的驴工作。但这引入了它自己的问题,因为你只能从一个线程访问显示控件 - 你的应用程序开始的UI线程。例如,如果您尝试从不同的线程更改TextBox上的文本,您将获得交叉线程异常,您的应用程序将失败。有很多方法 - 它被称为调用控件 - 但这很难解释。



相反,请查看 BackgroundWorker类(System.ComponentModel) [ ^ ] - 它允许您非常简单地设置第二个线程,并将进度事件报告回主线程,以便它可以更新控件以反映它。看看这个例子,还有ProgressChangedEventArgs,因为有一个UserState属性,可以让你发回有关作业进展到主线程的复杂信息。
When you write a Windows application, it starts with one thread - which means that it can do one thing at a time. If you are busy reading and processing lines from a file, then your application can't do anything else until you finish doing that - and that includes not responding to user input, or requests to change the display: because Windows works by sending messages to your app which it processes when it gets back to it's "idle loop" and looks for something to do. If you are keeping it busy looking at lines from files, then it never runs out of things to do and never looks at it's collection of messages.

So instead you need to start a second thread to do all the "donkey work" behind the scenes. But that introduces it's own problems, because you can only access display controls from a single thread - the UI thread that your app started with. If you try to change the text on a TextBox from a different thread for example, you will get a "Cross Threading Exception" and you app will fail. There are ways around that - it's called Invoking the control - but that gets complicated to explain.

So instead, look at the BackgroundWorker Class (System.ComponentModel)[^] - it allows you to very simply set up a second thread, and report progress events back to the main thread so it can update the controls to reflect it. Have a look at the example, and also at the ProgressChangedEventArgs as there is a UserState property which lets you send back complicated info on how the job is progressing to your main thread.


这篇关于为什么while循环挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆