Приостановить и возобновить цикл в C # - PullRequest
2 голосов
/ 13 октября 2010

Я работаю над приложением Windows в C #, у меня есть цикл for, который обновляет что-то в цикле, и у меня есть 3 кнопки в форме с именем «Стоп, Пауза, Возобновить».Таким образом, цель такая же, как у названных кнопок.Кто-нибудь знает, как это сделать?

Вот цикл

    private void btnCompleteAuto_Click(object sender, EventArgs e)
    {
        setGeneralValue();
        for (int i = 1; i <= autoGridView.Rows.Count - 1; i++)
        {
            if (SRP == "Pause") // this is what I was thinking but it won't work
            {                   // it will step into end-less loop
              do                // how to stop this loop on "Resume" button click
              {

              }while(SRP!="Resume")

            }
            car = false;
            try
            {
                MemberID = Convert.ToInt64(autoGridView.Rows[0].Cells["Member_ID"].Value);
                DispID = Convert.ToString(autoGridView.Rows[0].Cells["Disp_Id"].Value);
                Mobile = Convert.ToString(autoGridView.Rows[0].Cells["Mobile"].Value);
                DueDate = Convert.ToString(autoGridView.Rows[0].Cells["Due_Date"].Value);

            }
            catch (Exception)
            {
                MessageBox.Show("Row Not Found");
            }

            AutoRecharge(network_name, pack_name, Mobile, Mobile, Convert.ToString(autoGridView.Rows[0].Cells["Rck_Amt"].Value), vendor_id, vendor_pwd, pack_id, oxinetwork_id);
            autoGridView.Rows.RemoveAt(0);
        }
    }

Вот три события кнопки, в которых я устанавливаю переменную

    private void btnPause_Click(object sender, EventArgs e)
    {
        SRP = "Pause";
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        SRP = "Stop";
        autoGridView.DataSource = "";
    }

    private void btnResume_Click(object sender, EventArgs e)
    {
        SRP = "Resume";
    }

Ответы [ 2 ]

4 голосов
/ 13 октября 2010

Причина, по которой это не работает так, как вы ожидаете, заключается в следующем:

Приложение Windows Forms использует отдельный поток пользовательского интерфейса, который постоянно обрабатывает входящие сообщения из очереди.Любые обработчики событий, которые вы присоединяете к событиям элемента управления Windows Forms, отправляются в эту очередь и обрабатываются потоком пользовательского интерфейса как можно быстрее.

Ваш btnCompleteAuto_Click является одним из таких обработчиков.Как только он запускается, ничего больше не будет обрабатываться потоком пользовательского интерфейса, пока он не выйдет из .Таким образом, любые другие обработчики , которые вы присоединяете к другим событиям (btnPause_Click, btnStop_Click и т. Д.), Должны ждать своей очереди, поскольку они будут выполняться в том же потоке (UI).

Если вы хотите, чтобы функция паузы / возобновления работала, это имеет , которая должна быть достигнута в отдельном потоке.

Возможный способ реализовать это - использовать BackgroundWorker, как предложено saurabh .

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

Однако вы должны знать, что доступ к элементам управления UI напрямую из потока, не являющегося UI,нет-нет.Используйте механизм, такой как событие BackgroundWorker.ProgressChanged, для обработки любых обновлений пользовательского интерфейса, которые должны произойти на основе активности в потоке без пользовательского интерфейса.

ManualResetEvent _busy = new ManualResetEvent(false);

private void btnCompleteAuto_Click(object sender, EventArgs e)
{
    if (!backgroundWorker.IsBusy)
    {
        _busy.Set();
        btnAutoCompleteAuto.Text = "Pause";
        backgroundWorker.RunWorkerAsync();
    }
    else
    {
        _busy.Reset();
        btnAutoCompleteAuto.Text = "Resume";
    }

    btnStop.Enabled = true;
}

private void btnStop_Click(object sender, EventArgs e)
{
    _busy.Set();
    backgroundWorker.CancelAsync();
}

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // for (something)
    // {

        _busy.WaitOne();

        if (backgroundWorker.CancellationPending)
        {
            return;
        }

        // Do your work here.

    // }
}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    _busy.Reset();
    btnAutoCompleteAuto.Text = "Start";
    btnStop.Enabled = false;
}
2 голосов
/ 13 октября 2010

После прочтения вашего фактического требования в нашем комментарии я бы предложил использовать класс рабочего класса, который поддерживает отмену запущенного процесса.

Смотрите здесь

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