单独线程中的计时器

发布于 2025-01-04 20:37:37 字数 4801 浏览 0 评论 0原文

我想在单独的线程中创建一个计时器,但我不知道该怎么做。 单击一个按钮后计时器应停止。

下面我有一个大部分有效的示例,但在执行循环时有时会停止 1-2 秒。所以我想我必须把它放在一个单独的线程中?这是我尝试过的:

    private void buttonStop_Click(object sender, EventArgs e)
    {
        timer1.Stop();
    }

    public void TimeThread()
    {
        th = new Thread(new ThreadStart(Timer));
        th.Start();
    }

    public void Timer()
    {
        var delta = DateTime.Now - startTime;
        textBoxSeconds.Text = delta.Seconds.ToString("n0");
        textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
    }

编辑: 这是我拥有的所有代码,但仍然不确定如何将计时器放在单独的线程中。

namespace Imgur
{
    public partial class Form1 : Form
    {
        bool flag = true;
        int downloadedNumber = 0;
        private DateTime startTime;

        public Form1()
        {
            InitializeComponent();
        }

        public void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            buttonStop.Enabled = true;
            if (!flag)
            {
                flag = true;
            }

            startTime = DateTime.Now;
            timer1.Start();


            for (int i=0;i<100000 && flag;i++)
            {
                WebClient webClient = new WebClient();
                string pic1 = rnd_str(5);
                string pic2 = ".jpg";
                string picture = pic1 + pic2;

                //********** GETTING SIZE OF IMAGE ***********
                Size sz = GetSize("http://i.imgur.com/" + picture);
                string imageSize = (sz.Width.ToString() + " " + sz.Height.ToString()); ;
                //********************************************

                if(imageSize != "161 81")
                {
                    webClient.DownloadFile("http://i.imgur.com/" + picture, @"e:\test\" + picture);
                    richTextBox1.Text += String.Format("Downloaded picture: {0}\r\n", picture);
                    downloadedNumber++;
                    textBoxDownloadedNumber.Text = string.Format("{0}", downloadedNumber);
                }
                webClient.Dispose();
                Application.DoEvents();
                if (i == 999995)
                {
                    flag = false;
                }
            }
            richTextBox1.Text += "End Dowloaded Session \n";
            buttonStart.Enabled = true;
            buttonStop.Enabled = false;
            timer1.Stop();
        }

        public static Size GetSize(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.Accept = "image/gif";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream s = response.GetResponseStream();
            Bitmap bmp = new Bitmap(s);
            Size sz = new Size(bmp.Width, bmp.Height);
            return sz;
        }

        public static string rnd_str(int liczba_liter)
        {
            Random r = new Random();
            int char_type;
            string return_string = "";
            int i =0;
            for (i = 0; i < liczba_liter; i++)
            {
                if (r.Next(1, 3) == 1)
                {
                    char_type = r.Next(1, 4);
                    switch (char_type)
                    {
                        case 1:
                            return_string += (char)r.Next(48, 58); // convertion int -> ASCII character; 48-57 are ASCII digits
                            break;
                        case 2:
                            return_string += (char)r.Next(97, 123); // convertion int -> ASCII character; as above but small letters
                            break;
                        case 3:
                            return_string += (char)r.Next(65, 91); // as above; large letters
                            break;
                        default:
                            i -= 1;
                            break;//do not add any letter if no type is allowed
                    }
                }
                else
                {
                    i -= 1;
                    return_string += "";
                }
            }
            return return_string;
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            flag = false;
            buttonStart.Enabled = true;
            timer1.Stop();
        }

        public void timer1_Tick(object sender, EventArgs e)
        {
            var delta = DateTime.Now - startTime;
            textBoxSeconds.Text = delta.Seconds.ToString("n0");
            textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
        }
    }
}

I want to create a timer in a separate thread, but I'm not sure how to do it.
The timer should stop after clicking button a button.

Below I have an example that mostly works but it stops sometimes for 1-2 seconds when the loop is executing. So I guess I have to put it in a separate thread? This is what I've tried:

    private void buttonStop_Click(object sender, EventArgs e)
    {
        timer1.Stop();
    }

    public void TimeThread()
    {
        th = new Thread(new ThreadStart(Timer));
        th.Start();
    }

    public void Timer()
    {
        var delta = DateTime.Now - startTime;
        textBoxSeconds.Text = delta.Seconds.ToString("n0");
        textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
    }

EDIT:
So here is all the code that I have, still not exactly sure how to put the timer in separate thread.

namespace Imgur
{
    public partial class Form1 : Form
    {
        bool flag = true;
        int downloadedNumber = 0;
        private DateTime startTime;

        public Form1()
        {
            InitializeComponent();
        }

        public void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            buttonStop.Enabled = true;
            if (!flag)
            {
                flag = true;
            }

            startTime = DateTime.Now;
            timer1.Start();


            for (int i=0;i<100000 && flag;i++)
            {
                WebClient webClient = new WebClient();
                string pic1 = rnd_str(5);
                string pic2 = ".jpg";
                string picture = pic1 + pic2;

                //********** GETTING SIZE OF IMAGE ***********
                Size sz = GetSize("http://i.imgur.com/" + picture);
                string imageSize = (sz.Width.ToString() + " " + sz.Height.ToString()); ;
                //********************************************

                if(imageSize != "161 81")
                {
                    webClient.DownloadFile("http://i.imgur.com/" + picture, @"e:\test\" + picture);
                    richTextBox1.Text += String.Format("Downloaded picture: {0}\r\n", picture);
                    downloadedNumber++;
                    textBoxDownloadedNumber.Text = string.Format("{0}", downloadedNumber);
                }
                webClient.Dispose();
                Application.DoEvents();
                if (i == 999995)
                {
                    flag = false;
                }
            }
            richTextBox1.Text += "End Dowloaded Session \n";
            buttonStart.Enabled = true;
            buttonStop.Enabled = false;
            timer1.Stop();
        }

        public static Size GetSize(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.Accept = "image/gif";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream s = response.GetResponseStream();
            Bitmap bmp = new Bitmap(s);
            Size sz = new Size(bmp.Width, bmp.Height);
            return sz;
        }

        public static string rnd_str(int liczba_liter)
        {
            Random r = new Random();
            int char_type;
            string return_string = "";
            int i =0;
            for (i = 0; i < liczba_liter; i++)
            {
                if (r.Next(1, 3) == 1)
                {
                    char_type = r.Next(1, 4);
                    switch (char_type)
                    {
                        case 1:
                            return_string += (char)r.Next(48, 58); // convertion int -> ASCII character; 48-57 are ASCII digits
                            break;
                        case 2:
                            return_string += (char)r.Next(97, 123); // convertion int -> ASCII character; as above but small letters
                            break;
                        case 3:
                            return_string += (char)r.Next(65, 91); // as above; large letters
                            break;
                        default:
                            i -= 1;
                            break;//do not add any letter if no type is allowed
                    }
                }
                else
                {
                    i -= 1;
                    return_string += "";
                }
            }
            return return_string;
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            flag = false;
            buttonStart.Enabled = true;
            timer1.Stop();
        }

        public void timer1_Tick(object sender, EventArgs e)
        {
            var delta = DateTime.Now - startTime;
            textBoxSeconds.Text = delta.Seconds.ToString("n0");
            textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北音执念 2025-01-11 20:37:37

在您的代码中,计时器和经过的时间的打印之间似乎没有任何联系。
您需要注意,因为不可能从非主线程的另一个线程更改 GUI 元素。
为此,您需要在 WinForms 中使用 Invoke

if (control.InvokeRequired)
  {
    control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
  }
  else
  {
    control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
  }

或在 WPF/SL 中使用调度程序 - http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher

为了使用另一个线程,你有一些选择:

  1. 线程池(在.Net 4) - http://msdn.microsoft.com /en-us/library/3dasc8as(v=vs.80).aspx
  2. 线程类 - http://msdn.microsoft.com/en-us/ Library/aa645740(v=vs.71).aspx
  3. 后台工作类 - http://msdn.microsoft.com/en-us/ library/cc221403(v=vs.95).aspx

如果您不知道如何使用 theards,第三个选项是最简单的

In your code it seems there is no connection between the timer and the print of the time passed.
You need to pay attention because it isn't possible to change GUI elements from another thread that isn't the main one.
To do this you need to use Invoke in WinForms

if (control.InvokeRequired)
  {
    control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
  }
  else
  {
    control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
  }

or dispatcher in WPF/SL - http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher

In order to use another thread and you have some options:

  1. Threadpool (On .Net 4) - http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx
  2. Thread class - http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
  3. BackgroundWorker Class - http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

The 3rd option is the easiest if you don't know how to work with theards

歌枕肩 2025-01-11 20:37:37

.Net 中有树计时器,请查看以下文章并选择正确的 计时器 看起来您需要来自 System.Threading 的计时器,而不是来自 System.Windows.Forms 的计时器。

There're tree Timers in .Net take a look at the following article and select correct timer looks like you need timer from System.Threading, not from System.Windows.Forms.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文