Моя программа блокируется, когда я запускаю таймер, и я не уверен, почему - PullRequest
0 голосов
/ 25 января 2012

Я создал 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 ]

1 голос
/ 25 января 2012

Я собираюсь сделать предположение здесь, так как у нас недостаточно информации. Я предполагаю, что tmrInterval в System.Windows.Forms.Timer. Если это так, то, что происходит, когда таймер срабатывает, он передается в виде сообщения Windows (так же, как обрабатываются щелчки мыши, нажатия клавиш и все остальное, что делает ваше приложение «не замороженным»).

В первом приложении вы делаете что-то, что требует значительного времени - открывая порт TCP, затем ожидая (предположительно) большое количество миллисекунд, пока TCP не подключится или не подключится, а затем почти сразу же сделает это снова в следующий раз, когда таймер тикает. Вы буквально никогда не предоставляете приложению возможность реагировать на щелчки мыши и нажатия клавиш, потому что поток пользовательского интерфейса занят попыткой подключения к некоторым случайным портам где-то.

Во втором приложении вы делаете что-то относительно быстро - просто отправляете пинг куда-нибудь. во втором приложении вы, вероятно, увидите, что ваше приложение «заикается» - перестает отвечать на запросы в течение секунды или меньше, пока оно пингует любую другую машину, на которую вы указали. Он не зависает, потому что потоку пользовательского интерфейса не так много работы.

Чтобы исправить оба этих фактора, вы должны изучить реализацию BackgroundWorker . Таймеры (любого рода) обычно не считаются хорошим способом порождения фоновых задач в .NET.

1 голос
/ 25 января 2012

о первом образце:

Я полагаю из контекста, что таймер является Windows.Forms.Timer. В прошедшем событии вы выполняете WaitOne () и таким образом эффективно блокируете Messagepump.

В качестве возможного решения замените таймер на Threading.Timer, чтобы отделить ввод-вывод от основного потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...