如何从外部中止任务列表 [英] How to abort a list of tasks from the outside

查看:162
本文介绍了如何从外部中止任务列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于.net 4.5中的线程模型(或与此相关的一般线程),我还是一个相当陌生的人。我正在尝试构建一组抽象类,以实现用于对一系列类似任务进行多线程处理的框架。规则是输入的第一行告诉集合中有多少个问题,接下来的行包含每个问题的输入。组成一组输入的多少行可以从一个任务到下一个任务,但对于给定类型的问题通常是一致的。每个问题都是输出一行文本。

I am still fairly new to the threading model in .net 4.5 (or threading in general for that matter). I am trying to build a set of abstract classes in order to implement a framework for multithreading a series similar tasks. The rules are that the first line of the input tells how many problems are in the set, and the following lines contain the input for each problem. How many lines of input make up a set can vary from one task to the next, but are normally consistent for a given type of problem. Each problem is to have a single line of text as its output.

目标是能够从这些类继承,而不必担心实现CreateWorker和DoWork方法。 UI将调用ProcessInput开始操作,并调用WriteOutput列出结果。

The goal is to be able to inherit from these classes and only have to worry about implementing the CreateWorker and DoWork methods. The UI will call ProcessInput to get things started, and WriteOutput to list off the results.

到目前为止,我拥有的基本模板是:

The basic template I have so far is:

public abstract class Wrapper
{
    protected int N;
    protected WorkerBase[] ProblemSet;
    protected List<Task> Tasks;

    public virtual void ProcessInput(TextReader input)
    {
        string Line = input.ReadLine();
        N = int.Parse(Line);
        ProblemSet = new WorkerBase[N];
        Tasks= new List<Task>(N);
        for (int index = 0; index < N; index++)
        {
            WorkerBase T = CreateWorker(input);
            Tasks.Add(T.DoWorkAsync());
            ProblemSet[index] = T;
        }
    }

    public virtual bool WriteOutput(TextWriter outputStream, int timeout)
    {
        bool Complete = Task.WaitAll(Tasks.ToArray(), timeout);

        for (int index = 0; index < N; index++)
        {
            outputStream.WriteLine(ProblemSet[index].Result);
        }

        return Complete;
    }

    protected abstract WorkerBase CreateWorker(TextReader inputStream);
    protected abstract class WorkerBase
    {
        public string Result
        {
            get;
            protected set;
        }
        protected abstract void DoWork();
        public Task DoWorkAsync()
        {
            return Task.Run(() => DoWork());
        }
    }
} 

现在,这是会议我的要求。但是,现在我想向能够停止所有线程的Wrapper类添加中止功能。因此,问题是,如何以单击取消按钮的方式使UI可以中止进程,将中止功能用于此结构?最好不必在DoWork实现中编写额外的代码。

As is, this is meeting my requirements. But now I would like to add abort functionality to the Wrapper class which is capable of halting all of the threads. So the question is, how do I work the abort functionality into this structure in such a way that my UI can abort the process if a cancel button is clicked? Preferably without having to write extra code in the DoWork implementation.

我已经找到了传递取消标记的模式以中止任务,但是我发现了每个版本将要求DoWork检查令牌的状态并自行中止。我真的很想从方法外部中止DoWork。

I have found patterns which pass in a cancelation token in order to abort the task, but every version I have found would require that DoWork check the state of the token and abort itself. I really want a way to abort DoWork from outside the method.

推荐答案

中止正在运行的代码可以通过两种方法来完成(嗯,如果您包含它永远不会从待办事项队列中开始,我会怀疑这种情况3,我怀疑已取消任务已经发生了),其中只有一个是理智的:

Aborting running code can be done in two ways (well, kinda 3 if you include "it never gets started from the queue of things to do", which I suspect already happens for cancelled tasks), only one of which is sane:


  • 该工作会定期检查一些中止标志并干净地终止自身

  • 您中止整个线程

第一个是您应该做的;在大多数情况下,它工作正常。第二个绝不是好主意。您甚至应该考虑的唯一情况是,您的整个过程都病入膏terminal,以至于您只想尽可能快地放下它(并从痛苦中解脱出来)。中止线程后,您很有可能将系统置于无法恢复的位置,因此绝不可将其用于大多数理智的操作。另外:您需要引用每个涉及的线程,而在这里没有。

the first is what you should be doing; in most cases it works fine. The second is virtually never a good idea. The only time you should even consider this is when your entire process is so terminally ill that you just want to put it down (and out of its misery) as fast as possible. After aborting threads, there's a fair chance that you've left the system in an irrecoverable position, so this should never be used for most sane operations. Also: you'd need to have a reference to each Thread involved, which you don't have here.

因此:剩下第一种情况。坦白说,我认为您应该在这里检查一下标志。但是,如果您的工作人员需要定期从某个地方获取值,另一种可行的方法是让所有输入属性/方法/ etc进行那里的检查,然后引发一个众所周知的异常,即您的工作人员仅在访问 foo.Count (或类似的变量)时可能会得到该异常。

So: that leaves the first case. Frankly, I think you should just get and check the flags here. However, another approach that can work well if your worker needs to periodically get values from somewhere, is to have all the input properties / methods / etc do the check there, and raise a well-known exception, i.e. your worker might get the exception when it is just accessing foo.Count (or similar).

但是,通常更可取的是正式检查取消并报告您已取消,以便可以维护任务的状态。我想您也可以从 catch 块中执行此操作。

It is however, generally preferable to formally check for cancellation and report that you cancelled, so that the status of the task can be maintained. I guess you could also do this from a catch block, though.

这篇关于如何从外部中止任务列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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