我需要在递归算法期间停止执行 [英] I need to stop execution during recursive algorithm

查看:59
本文介绍了我需要在递归算法期间停止执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在选择正确的方法来实现我的目标时遇到了问题.我正在研究算法教学系统,我正在使用 C#.我需要将我的算法分成几个步骤,每个步骤都包含一个递归.我必须在每一步后停止执行,然后用户可以使用我的 GUI 中的按钮移动到下一步(下一个递归).

I have a problem in choosing the right method to accomplish my goal. I'm working on Algorithms teaching system, I'm using C#. I need to divide my algorithm into steps, each step will contain a recursion. I have to stop execution after each step, user can then move to the next step(next recursion) using a button in my GUI.

经过搜索,线程是正确的选择,但我找到了几种方法:

After searching, threads was the right choice, but I found several methods:

  • (Thread.sleep/interrupt): 没用,我的 GUI 冻结了!!

  • (Thread.sleep/interrupt): didn't work, my GUI freezed !!

(暂停/恢复):我听说使用它是个坏主意.

(Suspend/Resume): I've read that it's a bad idea to use.

(Waithandles):仍在阅读有关它们的信息.

(Waithandles): still reading about them.

(监控等待/恢复).

我没有太多时间尝试阅读所有以前的方法,请帮助我选择适合我系统的最佳方法.任何建议都非常欢迎.

I don't have much time to try and read all previous methods, please help me in choosing the best method that fits my system.Any suggestions are extremal welcomed.

推荐答案

从根本上说,这个问题与递归或多线程无关,只是这样:

Fundamentally, this question is not really about recursion or multi-threading, it is simply this:

如何在 GUI 应用的后台执行长时间运行的操作,以便应用保持响应?

How do I execute a long-running operation in the background of a GUI app so that the app stays responsive?

实现您自己的线程模型不是这里的方法,尤其是当您刚刚开始学习多线程/异步操作时..NET Framework 已经一个组件来满足您的需求:BackgroundWorker,适用于 Winforms 和 WPF(以及几乎所有其他架构).

Implementing your own threading model is not the way to go here, especially if you are just starting to learn about multi-threaded/async operations. The .NET Framework already has a component for what you want to do: BackgroundWorker, which works in both Winforms and WPF (and almost any other architecture).

使用BackgroundWorker 做你想做的事情非常非常容易.我将在此示例中使用 Winforms,但这是 在 WPF 中同样简单.

It is very, very easy to do what you want using the BackgroundWorker. I'll assume Winforms for this example but this is just as easy in WPF.

// Don't actually write this line; it will be in the .designer.cs file when you
// drop a BackgroundWorker onto the form/control.  This is for reference only.
private BackgroundWorker bwRecursive;

private void bwRecursive_DoWork(object sender, DoWorkEventArgs e)
{
    MyTreeNode root = (MyTreeNode)e.Argument;
    ExecuteRecursiveOperation(root);
}

private void bwRecursive_RunWorkerCompleted(object sender,
    RunWorkerCompletedEventArgs e)
{
    // Optionally update the GUI with the results here
}

private void ExecuteRecursiveOperation(MyTreeNode node)
{
    if (bwRecursive.CancellationPending)
        return;

    foreach (MyTreeNode childNode in node.ChildNodes)
    {
        if (bwRecursive.CancellationPending)
            break;

        ExecuteRecursiveOperation(childNode);
    }
}

您显然还必须连接 DoWorkRunWorkerCompleted 事件,并确保将 WorkerSupportsCancellation 设置为 trueBackgroundWorker 上的 code>.之后,您使用以下命令运行操作:

You obviously also have to wire up the DoWork and RunWorkerCompleted events, and make sure to set WorkerSupportsCancellation to true on the BackgroundWorker. After that, you run the operation with:

bwRecursive.RunWorkerAsync(someTreeNode);

并取消:

bwRecursive.CancelAsync();

<小时>

这里唯一的问题是你说你想在每个步骤"之后暂停(而不是停止)执行.我可能会使用 AutoResetEvent 来做到这一点,这是一种每次等待成功时重置其信号(就绪")状态的事件.同样,只需几行代码即可集成:


The only wrinkle here is that you say you want to pause (not stop) execution after each "step". I would probably do this using an AutoResetEvent, which is a type of event that resets its signaled ("ready") state every time a wait succeeds. Again, it's only a few lines of code to integrate:

public class MyForm : Form
{
    private AutoResetEvent continueEvent = new AutoResetEvent(false);

    // Previous BackgroundWorker code would go here

    private void ExecuteRecursiveOperation(MyTreeNode node)
    {
        if (bwRecursive.CancellationPending)
            return;

        foreach (MyTreeNode childNode in node.ChildNodes)
        {
            continueEvent.WaitOne();  // <--- This is the new code

            if (bwRecursive.CancellationPending)
                break;

            ExecuteRecursiveOperation(childNode);
        }
    }

    private void btnContinue_Click(object sender, EventArgs e)
    {
        continueEvent.Set();
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        bwRecursive.CancelAsync();
        continueEvent.Set();
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        continueEvent.Set();
        bwRecursive.RunWorkerAsync(...);
    }
}

这里有一点可能需要额外解释,那就是取消方法,它首先取消然后设置 continueEvent.这样做是有必要的,因为如果工作人员仍在等待事件,它实际上不会进入取消阶段,所以当你取消时,你需要让工作人员继续.如果您希望在不需要用户点击继续"的情况下执行第一步,您还需要在 启动 Worker 时设置 continueEvent.

There's one thing that might warrant additional explanation here and that is the cancel method, which first cancels and then sets the continueEvent. It's necessary to do this because if the worker is still waiting for the event, it won't actually get to the cancellation stage, so when you cancel, you need to allow the worker to continue. You also need to set the continueEvent when you start the worker if you want it to execute the first step without requiring the user to hit "continue."

这篇关于我需要在递归算法期间停止执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆