【问题标题】:Pause and Resume a For-Loop in C#在 C# 中暂停和恢复 For 循环
【发布时间】:2015-05-11 17:27:45
【问题描述】:

我正在使用 C# 开发 Windows 应用程序,我有一个 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);
        }
    }

这是我设置变量的 3 个按钮事件

    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";
    }

【问题讨论】:

  • 你做错了。该循环要做的就是在不断全速循环的同时占用大量资源。
  • @Harry:hmm,你有什么建议?
  • 阅读状态机。您的 for 循环需要在暂停时保存其状态,然后提前退出循环。然后恢复按钮需要从保存状态开始。状态可以像i 的值一样简单,或者包括任意数量的其他局部变量。如果您想在应用程序的执行过程中保存状态,则需要担心保存类字段,但对于简单的暂停/恢复,这些字段应该已经保持不变。

标签: c#


【解决方案1】:

这不起作用的原因是:

Windows 窗体应用程序使用一个单个 UI 线程,该线程持续处理来自队列的传入消息。您附加到 Windows 窗体控件事件的任何事件处理程序都会被发送到此队列并由 UI 线程尽快处理。

您的btnCompleteAuto_Click 就是这样的处理程序之一。一旦启动,UI 线程在退出之前不会处理其他任何事情。因此,您附加到 other 事件(btnPause_ClickbtnStop_Click 等)的任何 other 处理程序都必须等待轮到它们,因为它们将在同一个 (UI) 上运行线程。

如果你想要暂停/恢复功能,这个必须在一个单独的线程上实现。

实现它的一种可能方法是使用BackgroundWorker,如suggested by saurabh

这是您更新的代码可能看起来的粗略草图(我什至没有尝试编译这个,更不用说调试它了;它只是作为一个您如何完成此功能的基本概述)。

但是,您需要注意,直接从非 UI 线程访问 UI 控件是不允许的。使用诸如 BackgroundWorker.ProgressChanged 事件之类的机制来处理您需要根据非 UI 线程上的活动进行的任何 UI 更新。

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】:

    在我们的评论中阅读您的实际要求后,我建议使用支持取消正在运行的进程的后台工作类。

    See here

    【讨论】:

    • 我的应用程序不断更新 serverDB 从 localDB 获取数据,即从 localDB 获取数据,它更新到 serverDB...所以我在循环中执行此操作,现在我想要一个选项让客户端暂停,继续甚至停止该过程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2011-08-08
    相关资源
    最近更新 更多