调用方法 x 次,持续时间为 x 秒

本文关键字:持续时间 方法 调用 | 更新日期: 2023-09-27 18:35:21

鉴于方法在 1 秒内,我正在尝试尽可能多地调用该方法,所以我决定使用计时器来帮助执行此操作,但是当计时器运行 tick 事件处理程序(1 秒后)时,该方法仍然被调用 - 我已经启动了它,如下所示:

public partial class Form1 : Form
    {
        public static Timer prntScreenTimer = new Timer();
        public Form1()
        {
            InitializeComponent();
            startCapture();
        }
        private static void startCapture()
        {
            prntScreenTimer.Tick += new EventHandler(prntScreenTimer_Tick);
            prntScreenTimer.Start();
            prntScreenTimer.Interval = 1000;
            while (prntScreenTimer.Enabled)
            {
                captureScreen();
            }
        }
        private static void prntScreenTimer_Tick(object sender, EventArgs e)
        {
            prntScreenTimer.Stop();
        }
        private static void captureScreen()
        {
            int ScreenWidth = Screen.PrimaryScreen.Bounds.Width;
            int ScreenHeight = Screen.PrimaryScreen.Bounds.Height;
            Graphics g;
            Bitmap b = new Bitmap(ScreenWidth, ScreenHeight);
            g = Graphics.FromImage(b);
            g.CopyFromScreen(Point.Empty, Point.Empty, Screen.PrimaryScreen.Bounds.Size);
            // Draw bitmap to screen
            // pictureBox1.Image = b;
            // Output bitmap to file
            Random random = new Random();
            int randomNumber = random.Next(0, 10000);
            b.Save("printScrn-" + randomNumber, System.Drawing.Imaging.ImageFormat.Bmp);
        }
    }
}

调用方法 x 次,持续时间为 x 秒

我相信

问题是您在startcapture中阻塞了主线程。表单计时器需要处理消息才能运行。将循环更改为:

    while (prntScreenTimer.Enabled)
    {
        captureScreen();
        Application.DoEvents();
    }

由于您不需要从您的方法访问 UI 线程,因此会更好,因为它不会阻止 UI:

private void startCapture()
{
    Thread captureThread = new Thread(captureThreadMethod);
    captureThread.Start();
}
private void captureThreadMethod()
{
   Stopwatch stopwatch = Stopwatch.StartNew();
   while(stopwatch.Elapsed < TimeSpan.FromSeconds(1))
   {
       captureScreen();
   }        
}

您的代码对我来说看起来是正确的,所以我无法确定您的问题的原因。但是,您实际上并不需要对正在做的事情进行Timer;在while循环中检查一个简单的Stopwatch可能就足够了:

Stopwatch sw = Stopwatch.StartNew();
while (sw.ElapsedMilliseconds < 1000)
    captureScreen();

该方法被调用了多少次?你是如何计算的(无法从你粘贴的代码中看出来)。
无论情况如何,您都必须记住已用事件在单独的线程上运行,因此这种争用条件是可能的(您的方法在您触发计时器后运行一次甚至更多次)。当然,有一些方法可以防止这种竞争条件。这里存在一个有点复杂的示例,在 msdn 上