如何在循环中等待(Vb.net问题) [英] How to Wait in Loop (Vb.net problem)

查看:103
本文介绍了如何在循环中等待(Vb.net问题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好!
我当然是这里的新成员,我也是VB.NET的新手.

好吧,我不是英语还是美国人...,所以我不会说英语,对此感到抱歉.
但是在这种情况下,我确实需要帮助.我用Visual Studio 2008创建了一个VB应用程序.它称为随机数".

我要进行该应用程序是因为我有一家女鞋店,所以我想在我的计算机上制作一个程序,以随机价格显示产品.在可以执行该程序之前,该随机数"应用程序是我的第一个小测试.

让我们开始我的问题,嗨.

好吧,这是我的应用程序图形:


< img src ="http://i375.photobucket.com/albums/oo199/congchuatimhoangtu1989/random1.jpg">

如您所见,我的应用程序包含四个主要部分:
-较低的数字(txtLower):这是我输入最低数字的地方.
-较高的数字(txtHigher):这是我放入最高数字的地方.
-按钮随机开始(btRandom):用于激活程序的按钮.
-标签随机(lbRandom):这是较低数字和较高数字之间的随机数字"显示的地方.

我想要一个可以放置最低和最高数字的应用程序,然后程序将自动显示它们之间的随机数.

所以,我让我像这样的代码进行循环测试:

Hi everybody!
I''m a new member here and ofcourse, I''m a newbie of VB.NET, too.

Well, I am not an English or American..., so I am not good at English, sorry about that.
But I really need help in this situation. I created an VB application by Visual Studio 2008. It called "Random Number".

I want to make that application because I have a girl shoes shop, so I want to make a program show Random product with its price in my computer. That "random number" application is my small first test before I can do that program.

Let''s begin my problem, hihi.

Well, this is my application graphic:


<img src="http://i375.photobucket.com/albums/oo199/congchuatimhoangtu1989/random1.jpg">

As you can see, my application has 4 main parts:
- Lower number (txtLower): This is where I put the Lowest number.
- Higher number (txtHigher): This is where I put the Highest number.
- Button Random Begin (btRandom): button to activate the program.
- Lable Ramdom (lbRandom): this is where the "random number" between Lower and Higher number show up.

I want an application where I can put Lowest and Highest number and then the program will show the random number between them automatically.

So, I make I loop test like this code:

Private Sub btRandom_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btRandom.Click

        Dim lower, higher, i As Integer
        Dim R As New Random
        lower = txtLower.Text
        higher = txtHigher.Text


        For i = 1 To 10
            lbRandom.Text = R.Next(lower, higher)
            Threading.Thread.Sleep(500)
        Next

End Sub



因此,作为我的测试代码,这意味着每经过0.5秒,就会出现一个随机数.
但是,问题是事实并非如此.实际上,它显示等待循环结束. 5秒钟后的平均值(因为我使用1到10的循环,每次500 ms),仅显示1个随机数.
这不是我想要的.

作为SAKryukov,我不应该使用Threading.Thread.Sleep和Appilcation.DoEvent.但是我只是VB的新手,所以如果您不介意,请向我展示其他解决方案的示例.谢谢你.

因此,如果您有时间,能否请您帮助我了解如何解决该问题.
非常感谢!



So, as my test code, it means after each 0,5 second, one random number will show up.
But, the problem is it was not. In fact, It wait for the loop end, it show. Means after 5 seconds (cause i use loop from 1 to 10, each time 500 ms), just 1 random number show.
It is not what I want.

As SAKryukov, I should not use Threading.Thread.Sleep and Appilcation.DoEvent. But I''m just a newbie of VB, so if you don''t mind, please show me an example of another solutions. Thank you.

So, if you have time, can you please help me to know how to solve that problem.
Thank you so much!

推荐答案

这是根据OP的请求创建的代码示例:



首先,让我们做一个线程包装器.稍后,您可以添加一些随机算法,并在其中输入数字范围.现在,重要的是要制作骨架:生成一些数字并以新值触发事件;同样,它可以被启动/暂停/恢复/中止.线程本身对用户是隐藏的.注意事件句柄的使用-这是使用长寿命线程并将其保持在等待状态而又不浪费任何CPU时间的方法.等待句柄时,线程将被切出,并且永远不会安排回执行,直到在任何其他线程中调用ManualResetEvent.Set,timeout或Abort唤醒该线程.

该线程是从UI中抽象出来的. UI线程负责将事件句柄添加到事件NumberGenerated的调用列表中.


线程包装器对于避免参数化的线程启动以及总体而言更好的封装非常重要.

请查看我过去的答案以获取更多详细信息:
如何将ref参数传递给线程 [ ^ ],
启动后更改线程(生产者)的参数 [ ^ ].

这是VB.NET的翻译:
将参数传递给线程化的LongRunningProcess [ VSNetVbHarry 非常好,可以完成这项工作.

[END EDIT]

This is a code sample created on OP''s request:



First, let''s make a thread wrapper. Later on, you can add some random algorithm, input numeric ranges in it. For now, it''s important to make a skeleton: generate some number and fire an event with new value; also, it can be started/paused/resumed/aborted. The thread itself is hidden for a user. Note the use of event handle — this is the way to use long-living thread and keep it in a wait state without wasting any CPU time. On a wait of the handle, a thread is switched out and never scheduled back to execution until waken up by the call to ManualResetEvent.Set, timeout or Abort called in any other thread.

The thread is abstracted from the UI. It''s responsibility of the UI thread to add an event handle to the invocation list of event NumberGenerated.



The thread wrapper is very important to avoid parametrized thread start and for better encapsulation in general.

Please see my past answers for more detail:
How to pass ref parameter to the thread[^],
change paramters of thread (producer) after it started[^].

This is a VB.NET translation:
Passing arguments to a threaded LongRunningProcess[^].

VSNetVbHarry was so nice to do this work.

[END EDIT]

namespace RandomTest {
    using System.Threading;
    
    internal class ThreadWrapper {

        internal class NumberGeneratedEventArgs : System.EventArgs {
            internal NumberGeneratedEventArgs(int number) { this.fNumber = number; }
            internal int Number { get { return fNumber; } }
            int fNumber;
        } //class NumberGeneratedEventArgs
        
        internal ThreadWrapper(int sleepTime) {
            this.thread = new Thread(this.Body);
            this.sleepTime = sleepTime;
        } //ThreadWrapper

        internal void Start() { this.thread.Start(); }
        internal void Abort() { this.thread.Abort(); }
        internal void Pause() { this.waitHandle.Reset(); }
        internal void Resume() { this.waitHandle.Set(); }

        internal event System.EventHandler<NumberGeneratedEventArgs>
            NumberGenerated;

        void Body() {
            int value = 0;
            while (true) {
                waitHandle.WaitOne();
                if (NumberGenerated != null)
                    NumberGenerated.Invoke(this, new NumberGeneratedEventArgs(value));
                value++;
                Thread.Sleep(sleepTime);
            } //loop
        } //Body
        
        Thread thread;
        int sleepTime;
        ManualResetEvent waitHandle = new ManualResetEvent(false); //non-signalled
    
    } //ThreadWrapper

} //namespace RandomTest



现在,让我们以表格形式使用它.我故意将其全部放在一个文件中,并避免使用Designer,因此所有代码都放在一个位置:



Now, let''s use it in the form. I intentionally made it all in one file and avoided use of Designer, so all code would be in one place:

namespace RandomTest {
    using System.Windows.Forms;

    public partial class FormMain : Form {

        const string ButtonStop = "&Stop";
        const string ButtonStart = "&Start";
        const int SleepTime = 500;

        delegate void NumberAction(Label label, int value);
        //in .NET version above 2.0 this line is not needed
        //use System.Action<Label, int> instead

        public FormMain() {
            Padding = new Padding(10);
            Button button = new Button();
            button.Text = ButtonStart;
            button.Dock = DockStyle.Bottom;
            Controls.Add(button);
            Label output = new Label();
            output.Dock = DockStyle.Fill;
            output.AutoSize = false;
            Controls.Add(output);
            button.Click += delegate(object sender, System.EventArgs eventArgs) {
                if (running) {
                    button.Text = ButtonStart;
                    wrapper.Pause();
                } else {
                    button.Text = ButtonStop;
                    wrapper.Resume();
                } //if
                running = !running;
            }; //button.click 
            wrapper.NumberGenerated += delegate(object sender, ThreadWrapper.NumberGeneratedEventArgs eventArgs) {
                output.Invoke(new NumberAction(delegate(Label label, int value) {
                    label.Text = value.ToString();
                }), output, eventArgs.Number);
            }; //wrapper.NumberGenerated
            wrapper.Start();
            this.Closing += delegate(object sender, System.ComponentModel.CancelEventArgs e) {
                wrapper.Abort();
            };
        } //FormMain

        bool running;
        ThreadWrapper wrapper = new ThreadWrapper(SleepTime);

    } //class FormMain

} //namespace RandomTest



我还尝试使用与仍在使用的C#v.2兼容的语法.我还希望,如果您仍然想在VB.NET中进行翻译,将会更容易.在更高版本中,匿名委托的lambda语法非常有用.

关于VB.NET,请参阅我对问题的评论.

此代码已经过全面测试.同样,抱歉,这不是VB.NET.

—SA



I also tried to use the syntax compatible with C# v.2, which is still used. I also hope it will be easier if you still want to translate it in VB.NET. In later versions, lambda syntax of anonymous delegates is highly beneficial.

As to VB.NET, please see my comment to the question.

This code is fully tested. Again, sorry this is not VB.NET.

—SA


请帮自己一个忙,不要执行Application.DoEvents,尤其是为此目的.这称为旋转等待,这是一件坏事.您永远不要执行任何阻塞调用,也不要在UI线程中调用Thread.Sleep.该线程应始终保持响应状态.

您需要创建一个单独的线程并在该线程中进行处理.要通知UI线程,您需要使用UI线程调用.请查看更多详细信息:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview Scanner和MD5问题 [如何获取keydown事件在vb.net中的不同线程上操作 [启用禁用+多线程后控件事件不会触发 [ ^ ].

—SA
Please do yourself a favor, don''t do Application.DoEvents, especially for this purpose. This is called spin wait and is a bad thing. You should never do any blocking call and never call Thread.Sleep in UI thread. This thread should be kept responsive at all times.

You need to create a separate thread and do your processing in that thread. To notify the UI thread, you need to use UI thread invocation. Please see for further detail:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading in my collection of links to my past answers:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA


这是WinForms项目,对吗?尝试将对Application.DoEvents()的调用放入循环中(在sleep调用之前); UI线程可能没有机会在进入睡眠之前实际更新标签.
This is a WinForms project, right? Try putting a call to Application.DoEvents() in the loop (before the sleep call); it''s possible that the UI thread is not getting a chance to actually update the label before it goes to sleep.


这篇关于如何在循环中等待(Vb.net问题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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