Отмена задачи без предоставления метода задачи с помощью CancellationTokenSource - PullRequest
0 голосов
/ 01 июня 2011

Я пытаюсь обеспечить функциональность двух методов, один из которых называется StartTask (action mymethod) а другой называется StopTask ();

проблема в том, что действие должно иметь доступ к CancellationTokenSource для проверки отмены и выхода из метода (возврата), который на самом деле не тот, который я хочу, чтобы метод мог быть в другом компоненте или слое, я не могу нажать каждый метод, чтобы иметь доступ к этой отмене, источник

Я не могу подтолкнуть дизайнера / разработчика компонента, у которого есть метод процесса, к проверке отмены и возврата.

есть ли способ получить что-то подобное, я знаю, это звучит странно и неприменимо, просто подумал спросить.

это лучшее, что я получил:

       CancellationTokenSource cancellationTokenSource;
    private void button1_Click(object sender, EventArgs e)
    {
        cancellationTokenSource = new CancellationTokenSource();
        Task t = new Task(() => Dowork(CancellationAction), cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
        t.Start();
    }
    private bool CancellationAction()
    {

        if (cancellationTokenSource.IsCancellationRequested)
        {
            label1.Invoke(new MethodInvoker(() =>
                                                {
                                                    label1.Text = "Cancellation Requested!";
                                                }));
            return true;
        }
        return false;
    }
    private void Dowork(Func<bool> Return)
    {
        int x = 1;
        while (true)
        {
            x++;
            label1.Invoke(new MethodInvoker(() =>
                                                {
                                                    label1.Text = x.ToString();
                                                }));
            Thread.Sleep(1000);
            if (Return())
            {
                return;
            }
        }
    }

проблема в том, что у DoWork теперь должен быть один параметр, который является func, но что если метод уже принимает другие параметры? создание задачи будет в другом классе, который может не иметь представления о том, какие параметры передавать, кроме CancellationAction

Ответы [ 3 ]

2 голосов
/ 01 июня 2011

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

Таким образом, в основном компонент нижнего уровня должен предоставить вызывающей стороне способ отменить задачу (ManualResetEvent, метод CancelAsync, такой как BackgroundWorker и т. Д.).В противном случае вызывающая программа должна дождаться его завершения.

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

0 голосов
/ 01 июня 2011

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

Сначала вы пытаетесь передать параметры асинхронному потоку и / или отменить этот поток (очень похожие проблемы). Как уже говорили другие, BackgroundWorker уже обрабатывает отмену. Эта реализация похожа на передачу любого аргумента в ваш поток. Например, если бы я реплицировал эту функцию, я бы добавил свойство или метод Cancel в свой рабочий поток, который любой другой компонент мог бы вызвать, и проверил значение поддержки в цикле основного потока. Нет причин делать это для отмены потоков в эти дни, только пример передачи и использования значений в рабочий поток.

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

например. (возможно, плохой пример, но ...) Если моя процедура проверки грамматики должна отменяться при закрытии документа, я бы определил событие DocumentClosing и метод OnDocumentClosing в интерфейсе IDocumentService и реализовал этот интерфейс в соответствующем контексте / модели. При создании компонента компонента пользовательского интерфейса средства просмотра документов и компонента проверки грамматики я вставляю экземпляр контекста / модели, введенный в качестве интерфейса. Когда средство просмотра документов начинает закрывать документ, оно вызывает метод OnDocumentClosing из интерфейса. Когда поток создается, он присоединяется к событию DocumentClosing, и, если событие запускается, устанавливается флаг. Затем с интервалами при проверке грамматики я проверял флаг и отменял при необходимости.

Реализация такого рода дает вам гибкость, позволяющую любому компоненту инициировать соответствующие события, и любой другой компонент реагирует на них независимо от того, где в вашем приложении используются компоненты. Фактически этот подход полезен даже в синхронных ситуациях, таких как изменение состояния пунктов меню в ответ на события приложения. Это позволяет легко модульное тестирование всех ваших компонентов. А разделение ответственности означает, что вы можете легко изменять любые триггерные точки и ответы по мере необходимости.

0 голосов
/ 01 июня 2011

Почему вы не используете BackgroundWorkerThread или другой механизм потоков?Есть ли особая причина для использования Task Parallel Library?

BackgroundWorkerThread даст вам возможность отменить задачу и затем отреагировать на отмену.

...