首页 新闻 会员 周边

谁能想出制造延迟的好办法?

0
悬赏园豆:100 [已解决问题] 解决于 2009-08-06 15:21

现在的需求是,执行一段代码,其功能是一串模拟按键,其中除了按键外还要插入几个延迟,主要是为了等待操作界面响应。

例如:

SendKeys.Send("A");

SendKeys.Send("{Enter}");

延迟(2000);

SendKeys.Send("{Esc}");

延迟(1000);

SendKeys.Send("D");

SendKeys.Send("E");

 

现在的问题就是,假如延迟方法采用Sleep:

void 延迟(int ms)

{

  Thread.Sleep(ms);

}

那么当前线程就被完全阻塞了,界面也就无法继续响应,等待半天都是白等,延迟后才继续执行所有界面响应,所以这样毫无意义。

我希望实现的效果是主线程转为空闲,让用户界面正常响应,延迟时间到了再继续执行下面的语句。

这样的话,多线程是可以实现的,但是又有一个问题,就是我不可能像最初那样写一行行的操作代码,中间穿插几个延迟函数调用,每次后续操作都只能依靠回调函数实现,假如我们的操作非常多,延迟也非常多,一个个回调嵌套回调,不仅难写,更难看,出了错也不好找啊。

不知道谁能用什么办法写出一个简单易用的延迟函数吗?就是这样的:

void 延迟(int ms)

{

  …………

}

问题补充: 两位朋友的提议我都进行了测试,简单的延迟输入字符都可以实现,但其他方面各自有些不足。 我进行了一个模拟键盘切换控件输入文字并打开和关闭对话框的测试,在界面中点击button3的事件被定义为打开一个对话框: private void button3_Click(object sender, EventArgs e) { openFileDialog1.ShowDialog(); } 以DoEvent方法测试: private void button2_Click(object sender, EventArgs e) { textBox1.Select(); SendKeys.Send("a"); SendKeys.Send("a"); SendKeys.Send("a"); SendKeys.Send("a"); button3.Select(); SendKeys.Send(" "); Wait(DateTime.Now.AddMilliseconds(3000)); SendKeys.Send("{Esc}"); Wait(DateTime.Now.AddMilliseconds(3000)); textBox1.Select(); SendKeys.Send("a"); SendKeys.Send("a"); } void Wait(DateTime t) { while (DateTime.Now < t) { Application.DoEvents(); } } 当对话框打开时整个过程就被卡住了,手动关闭后才恢复执行。 而eaglet提供的方法可以很好的解决这一问题,不足就是无法直接实现对主界面控件焦点的切换,还是需要做一些线程间交互工作,故此在下面的代码中只实现了对话框操控,没有做切换控件输入文字部分: private void button1_Click(object sender, EventArgs e) { button3.Select(); BackgroundWorker b = new BackgroundWorker(); b.DoWork += new DoWorkEventHandler(b_DoWork); b.RunWorkerAsync(); } void b_DoWork(object sender, DoWorkEventArgs e) { SendKeys.SendWait(" "); Thread.Sleep(3000); SendKeys.SendWait("{Esc}"); } 在此记录下来,以备日后参考。
斯克迪亚的主页 斯克迪亚 | 老鸟四级 | 园豆:4124
提问于:2009-08-05 16:08
< >
分享
最佳答案
0

发送按键的操作不要在主线程完成,单独起一个工作线程来做这个工作,这样你就可以在工作线程中用Sleep延时了。

如果你一定要在主线程做这个工作,可以考虑用定时器来搞。

 

收获园豆:60
eaglet | 专家六级 |园豆:17139 | 2009-08-05 18:03
这样也是不行的,可能是我没说详细,原因在于操作目标对象就在主线程中,即一个通过WebBrowser控件访问到得网页,如果我阻塞了主线程,任何相关操作都是无效的了。
斯克迪亚 | 园豆:4124 (老鸟四级) | 2009-08-05 22:15
你模拟按键的代码能否放到其它线程中跑?
eaglet | 园豆:17139 (专家六级) | 2009-08-06 14:44
@eaglet: 啊,是我开始理解错你的意思了,我以为是要我开辟一个线程执行按键,然后在主线程Sleep等待呢。 我笨了哈,在开辟的线程中执行并Sleep是可行的,就是得用SendWait方法而不是Send,唯一的缺憾就是没法直接切换主线程中的控件焦点状态。 非常感谢!!
斯克迪亚 | 园豆:4124 (老鸟四级) | 2009-08-06 15:05
其他回答(1)
0

使用Doevents吧,这个应该可以实现你的要求,就是系统资源有点浪费

收获园豆:40
zhykhld | 园豆:313 (菜鸟二级) | 2009-08-06 01:33
我测试一下,确实能够使主线程响应请求,但是假如主线程弹出一个系统对话框的话,整个代码执行过程就被阻塞了,预定的延迟时间被忽视,直到手动关闭对话框后才会继续计算延迟时间,这期间更是无法实现等待几秒后通过模拟按键操作弹出的对话框。 尽管如此,你的答案也非常有价值,十分感谢!
支持(0) 反对(0) 斯克迪亚 | 园豆:4124 (老鸟四级) | 2009-08-06 15:09
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册