在不使用CancellationTokenSource提供Task方法的情况下取消任务

时间:2011-06-01 13:14:45

标签: c# multithreading parallel-processing

我正在尝试提供一个名为StartTask的两个方法的功能(action mymethod) 另一个名为StopTask();

问题是操作必须有权访问CancellationTokenSource以检查取消并退出方法(返回)这不是我想要的方法可能在另一个组件或层中,我不能推动每个方法都有权访问到那个canceltokensource,

我无法推动具有处理方法的组件的设计者/开发者检查取消和返回。

有没有办法有这样的东西,我知道这听起来有点奇怪和不适用,只是想问。

这是我得到的最好的:

       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 个答案:

答案 0 :(得分:2)

如果组件没有提供取消其中一个正在运行的任务的方法,则调用方应该无法取消它。它可能使应用程序/数据库/任何处于未知状态。

所以基本上,较低级别的组件应该为调用者提供取消任务的方法(ManualResetEvent,CancelAsync方法,如BackgroundWorker等)。否则呼叫者应该等待它完成。

如果较低级别的组件没有提供这样的功能,那么大部分时间都被认为是糟糕的设计。

答案 1 :(得分:0)

为什么不使用BackgroundWorkerThread或其他线程机制? 是否有使用任务并行库的特殊原因?

BackgroundWorkerThread将为您提供更改以取消任务,然后回复取消。

答案 2 :(得分:0)

我不确定我是否完全理解你的问题,但我会抓住它。看起来你正试图在这里同时解决两个问题。

首先,您尝试将参数传递给异步线程和/或取消该线程(非常类似的问题)。正如其他人所说,BackgroundWorker已经处理取消。该实现类似于将任何参数传递给您的线程。如果我正在复制该功能,我会在我的工作线程中添加一个Cancel属性或方法,任何其他组件都可以在我的主线程循环中调用并检查支持值。这些天没有理由这样做取消线程,只是向工作线程传递和使用值的一个例子。

您需要解决的另一个问题是如何在应用程序的不同部分之间发送消息,否则这些消息不需要相互引用。通常情况下,我已经看到过某种服务提供商。在上下文或通用模型上实现接口,所有组件都接收实例或易于访问的实例。接口应包含任何事件,方法和属性,以便不同的组件可以进行通信。

E.g。 (可能是一个不好的例子但是......)如果我的语法检查例程应该在文档关闭时取消,我将在IDocumentService接口上定义DocumentClosing事件和OnDocumentClosing方法,并在适当的上下文/模型中实现该接口。在创建我的文档查看器UI组件和语法检查程序线程组件时,我将注入作为接口键入的上下文/模型的实例。当文档查看器开始关闭文档时,它从界面调用OnDocumentClosing方法。创建线程时,它将附加到DocumentClosing事件,如果事件触发,则设置标志。然后在检查语法时间隔,我会检查标志并在适当时取消。

这种实现使您可以灵活地让任何组件触发适当的事件,并且任何其他组件都会对它们做出反应,无论应用程序在何处使用组件。实际上,即使在诸如菜单项改变状态以响应应用程序事件的同步情况下,该方法也是有用的。它允许您对所有组件进行简单的单元测试。责任分离意味着您可以根据需要轻松更改任何触发点和响应。