当我启动计时器时我的程序锁定,我不知道为什么

时间:2012-01-25 19:22:43

标签: c# winforms timer

我创建了2个程序。两者都使用间隔设置为250毫秒的计时器。

问题是我的第一个程序没有锁定然后我运行它,第二个锁定没有让我能够点击停止按钮。通过说锁定我的意思是程序运行直到我从VS停止它。

我不明白为什么我不能停止我的第一个节目,而基本相同的方式适用于其他节目。有什么想法吗?

锁定程序:

    private void btnScan_Click(object sender, EventArgs e)
    {
        tmrInterval.Interval = (int)nudInterval.Value;
        tmrInterval.Start();
    }

    private void ScanPort(IPAddress address, int port)
    {
        using (TcpClient client = new TcpClient())
        {
            IAsyncResult result = client.BeginConnect(address, port, null, null);

            if (result.AsyncWaitHandle.WaitOne((int)nudTimeout.Value, false)) txtDisplay.AppendText("Port: " + port + " is open." + Environment.NewLine);
            else txtDisplay.AppendText("Port: " + port + " is closed." + Environment.NewLine);
        }
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        tmrInterval.Stop();
    }

    private void tmrInterval_Tick(object sender, EventArgs e)
    {
        ScanPort(IPAddress.Parse(txtIP.Text), currentPort);
        currentPort++;
        if (currentPort == nudTo.Value) tmrInterval.Stop();
    }

无法锁定的程序:

    void tmrPingInterval_Tick(object sender, EventArgs e)
    {
        if (txtTo.Text == string.Empty) Ping(IPAddress.Parse(ip2str(startIP)));
        else
        {
            if (currentIP >= endIP) tmrPingInterval.Stop();
            Ping(IPAddress.Parse(ip2str(currentIP)));
            currentIP++;
        }
    }

    private void btnPing_Click(object sender, EventArgs e)
    {
        if (txtFrom.Text != string.Empty)
        {
            txtFrom.Enabled = false;
            txtTo.Enabled = false;
            txtDisplay.Text = string.Empty;
            tsslPingCount.Text = string.Empty;
            count = 0;
            open = 0;
            closed = 0;
            tmrPingInterval.Interval = int.Parse(nudInterval.Value.ToString());

            try
            {
                startIP = str2ip(txtFrom.Text);
                if (txtTo.Text != string.Empty) endIP = str2ip(txtTo.Text);
                currentIP = startIP;
                tmrPingInterval.Start();
            }
            catch
            {
                MessageBox.Show("Input must be in IP format: 100.100.100.100", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtFrom.Enabled = true;
                txtTo.Enabled = true;
            }
        }
        else MessageBox.Show("IP field cannot be empty!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        txtFrom.Enabled = true;
        txtTo.Enabled = true;
        tmrPingInterval.Stop();
    }

    private void Ping(IPAddress address)
    {
        Ping pingSender = new Ping();
        PingOptions options = new PingOptions();
        if (cbDontFragment.Checked) options.DontFragment = true;
        else options.DontFragment = false;
        string data = string.Empty;
        int dataCounter = 0;
        options.Ttl = (int)nudTTL.Value;

        for (int i = 0; i < nudData.Value; i++)
        {
            dataCounter++;
            if (dataCounter == 10) dataCounter = 0;
            data += dataCounter.ToString();
        }

        byte[] buffer = Encoding.ASCII.GetBytes(data);
        int timeout = 120;
        try
        {
            PingReply reply = pingSender.Send(address, timeout, buffer, options);

            if (reply.Status == IPStatus.Success)
            {
            }
            else
            {
            }
        }
        catch (Exception ex)
        {
            txtDisplay.SelectedText += Environment.NewLine + ex.Message;
        }
    }

2 个答案:

答案 0 :(得分:1)

关于第一个样本:

我想从上下文来看,计时器是一个Windows.Forms.Timer。在elapsed事件中,您正在执行WaitOne(),因此有效地阻止了Messagepump。

作为一种可能的解决方案,用Threading.Timer替换Timer以将I / O与主线程分离。

答案 1 :(得分:1)

由于我们没有足够的信息,我将在这里猜测。我猜测System.Windows.Forms.Timer中的tmrInterval。如果是这种情况,那么正在发生的事情是,当计时器滴答时,它将被作为一个Windows消息传递(与鼠标点击,击键以及使您的应用程序显示为“未冻结”的所有其他内容的处理方式相同)。 / p>

在第一个应用程序中,你正在做一些花费大量时间的东西 - 打开一个TCP端口,然后等待(大概)大量的毫秒,直到TCP连接或没有,然后几乎立即再次执行它下次计时器滴答作响。你实际上永远不会给应用程序一个机会来响应鼠标点击和击键,因为UI线程正忙着尝试连接某个随机端口。

在第二个应用程序中,您正在做一些相对较快的事情 - 只需在某处发送ping。您可能会在第二个应用程序中看到的是,您的应用程序将“断断续续” - 只需一秒或更短时间就会无响应,同时它会ping您指向的其他任何计算机。它没有被挂起,因为没有给予UI线程很多工作要做。

要解决这两个问题,您应该考虑实施BackgroundWorker。定时器(任何类型)通常不被认为是在.NET中生成后台任务的好方法。