2013-05-04 8 views
0

Я по-прежнему довольно новичок в моделирование потоков в .net 4.5 (или на самом деле в этом плане). Я пытаюсь создать набор абстрактных классов, чтобы реализовать фреймворк для многопоточности серии подобных задач. Правила состоят в том, что первая строка ввода указывает, сколько проблем находится в наборе, а следующие строки содержат вход для каждой проблемы. Сколько строк ввода составляют набор, может варьироваться от одной задачи к другой, но обычно согласованы для заданного типа проблемы. Каждая проблема состоит в том, чтобы в качестве вывода выводилась одна строка текста.Как прервать список задач извне

Цель состоит в том, чтобы унаследовать эти классы и беспокоиться о внедрении методов CreateWorker и DoWork. Пользовательский интерфейс вызовет ProcessInput, чтобы начать работу, и WriteOutput перечислит результаты.

Основной шаблон у меня до сих пор:

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, который способен остановить все потоки. Итак, вопрос в том, как я могу работать с функциями прерывания в этой структуре таким образом, чтобы мой пользовательский интерфейс мог прервать процесс, если нажата кнопка отмены? Предпочтительно без необходимости писать дополнительный код в реализации DoWork.

Я нашел шаблоны, которые передают токен отмены, чтобы прервать задачу, но каждая найденная версия потребует, чтобы DoWork проверил состояние токена и прервал его. Я действительно хочу, чтобы прервать DoWork вне метода.

+0

Вы должны назвать свой список задач Задачами вместо потоков. Задача! = Поток, разные понятия.Для вашего вопроса ознакомьтесь с CancelationTokenSource http://msdn.microsoft.com/en-us/library/dd537607.aspx – jure

+0

Отмечено и переименовано в коллекцию. Я уже прочитал ссылку. Наделся на альтернативный образец. – Rozwel

ответ

2

Прекращение работы кода может быть выполнено двумя способами (ну, например, 3, если вы включите «он никогда не запускается из очереди вещей, которые нужно сделать», что, как я подозреваю, уже происходит для отмененных задач), только один из которых вменяемый:

  • работа периодически проверяет некоторые «прервать» флаг и завершает себя чисто
  • вы прервать всю нить

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

Итак: это оставляет первый случай. Честно говоря, я думаю, вам стоит просто посмотреть флажки. Однако, другой подход, который может хорошо работать , если вашему работнику необходимо периодически получать значения от где-то, должно быть все входные свойства/методы/и т. Д. Сделать отметку там и поднять известное исключение, то есть ваш рабочий может получить исключение, когда он просто обращается к foo.Count (или тому подобное).

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

Смежные вопросы