C#程序窗口假死

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#程序窗口假死相关的知识,希望对你有一定的参考价值。

我第一次编写windows窗口程序(C#),出现窗口假死现象,求解决思路。
是这样的,为了完成某个功能,需要顺序完成若干步骤,如果是多线程,不顺序也行,但每次只能执行一个小步骤,其它步骤必须等待当前步骤执行完才能执行。而且每个步骤之间需要加入一定的时间延迟,缓冲一下(必须这么做),按理说:采用以下语句最简洁: 步骤1; sleep();步骤2;sleep()……,但这样会造成窗口假死。最完善的办法可能是创建n个线程,每次延迟一定时间后执行下一线程,好是好,但需要建很多线程。我看到有人实现了自己的delay()方法,替换上述sleep()语句就可以执行,而且不会让窗口假死,不知是怎么实现的。网上搜索了一下,也没弄明白。这个delay方法,先不管它是怎么延时的,它应该让主线程(窗口线程)线程挂起(或等待)一段时间吧? 怎么让窗口线程在等待时不假死呢? 答案直接hi我也算,可以加分100以上,看回答质量了。
几位朋友回答都认真,我就再补充一下,我这个程序是模拟提交网页表单的。比如登录webqq等这类的操作。问题是由Thread.sleep()语句引起的。sleep会造成整个界面假死,但又不能不在两个操作(比如填写用户名算一个操作,填写密码是另一个操作)之间作一些延迟(主要作用是模拟手工操作)。所以延迟是必须的,这不是技术问题,是态度问题(开个玩笑,呵呵)。我看过模拟精灵写的程序,他就是用自己的 delay语句来代替sleep语句,不知是怎么实现的。

如果是用控制台的话,是不会有问题的;
如果是用窗体的话,就要用线程。
增加一个引用
using System.Threading;

然后弄一个线程出来

Thread asd = new Thread(abc)
asd.Start();

abc()

for(int i = 0;i==i;i++)
{}
参考技术A 每次只能执行一个,且步骤之间存在依赖性关系的话,那就不用多个线程,只用一个就可以了。
建议楼主用BackgroundWorker,多个步骤放在一个线程里面就行了。
多个线程还不是一个一个执行的吗?为啥要那么多线程呢,只要一个来保证窗口不假死就行了。追问

好象是比较好的解决方案,不了解BackgroundWorker,我先了解一下。
今晚了解了一下,看了一下BackgroundWorker的简介,其中有一句话似乎又把我的路堵住了:“您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。” 想想也是,既然把代码写到了非窗口线程中,那就应当和窗口联系不紧密才合理。而我的那些处理工作,却又恰恰要和界面打交道,我又迷茫了……

参考技术B 用个Timer撒,把执行的代码放在Timer的Tick方法里面,然后窗体上的某方法只执行timer1.Start();
就行了.Tick方法第一句写timer1.Stop();下面再放你的代码.
你在窗体上直接Sleep()不是卡UI了么.追问

应该是办法之一,不过有很多步骤, 具体要怎么操作呢,也有些麻烦吧?

追答

我上班的时候做读取窗口的时候就是用的这个方法
从数据库读取和遍历都很慢.,我就在Timer里面读取数据库和遍历List,这样就不会影响Form上面用来显示的Panel.
你知道你说的是我的这种情况不
protected void Page_Load(object sender, EventArgs e)

timer1.Start();

protected void timer1_Tick()

timer1.Stop();
……(后面写你说的卡主线程的语句)


我正在写个ASP.NET,随手写了下,语句肯定不符合Winform的,你看着情况改改看.

追问

我看到有人的确是用timer来做的,但我目前还不明白,应该怎么实现我的需求。(我的需求已经补充进来了,之前没看到的朋友可以看一下)

追答

我有几点没懂
1.程序是模拟提交网页表单的。比如登录webqq等这类?? 你的WINFORM程序是用的常规控件,还是用的比如WebBrowser
2.但又不能不在两个操作(比如填写用户名算一个操作,填写密码是另一个操作)之间作一些延迟 这啥意思,自动填写? 在TIMER中Sleep是不会严重影响到主UI.
3.所以延迟是必须的,这不是技术问题,是态度问题 什么态度问题??

本回答被提问者采纳
参考技术C 主要是因为UI线程被长时间的操作阻塞了。BackgroundWorker算是一种方法。如果不需要太多操作的话,还有一种更简单的方法。就是如果你在UI刷新过程中采用了长时间运算的for循环之类导致阻塞,可以试试在for中每次循环结束时,加一句Application.DoEvent() 。大致应该是这句,记不清了,自己查下。效果可能不如BackgroundWorker好,但是也能凑乎用。
最后只说一句,Vs2005的C# 和 Delphi太像了,应该是设计Delphi的人开发的,不过Vs2008开始已经超越Delphi了,现在的Delphi已是昔日黄花,太不给力了。追问

言之有理。

参考技术D 用其他线程去处理你要处理的东西,主线程还是做原来的生成窗体操作,我感觉是这样,你可以试试

以上是关于C#程序窗口假死的主要内容,如果未能解决你的问题,请参考以下文章

C# 窗口无假死,进度条

我用C# winform多线程,窗口就假死,等到线程全部完成了才可以点击。请问要怎么才可以让窗口不假死。

c#窗体假死

C#异步调用,界面假死

实现winfrom进度条及进度信息提示,winfrom程序假死处理

C# 委托 线程 窗体假死