2011-06-01 87 views
0

我试图提供两个方法之一称为StartTask(action mymethod) 和另一个称为StopTask()的功能;取消没有提供任务方法的任务与CancellationTokenSource

问题是操作必须有权访问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,但如果该方法已经采取其他的参数是什么?创建任务将在另一个类中,可能不知道在旁边传递哪些参数取消操作

+0

由于'CancellationTokenSource'暗示的名称,它意味着'CancellationToken'的* Source *,获得了我访问'Token'属性的权限。通常,模式是将'CancellationToken'传递给依赖任务。这就是说,我无法弄清楚你最终的代码示例是要达到什么目的。 – 2011-06-01 13:32:29

回答

0

我不确定我完全理解你的问题,但我会采取一个措施。看起来你正试图在这里一次解决两个问题。

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

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

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

这种实现方式使您可以灵活地让任何组件触发适当的事件和任何其他组件对他们作出反应,而不管应用程序中组件的使用位置。实际上,即使在同步情况下,这种方法也很有用,例如菜单项目响应应用程序事件而改变状态。它可以轻松对所有组件进行单元测试。责任分离意味着您可以根据需要轻松更改任何触发点和响应。

2

如果组件未提供取消某个正在运行的任务的方法,则调用方应该无法取消它。它可能会让应用程序/数据库/任何东西处于未知状态。

所以基本上,下层组件应该为调用者提供一种取消任务的方法(ManualResetEvent,CancelAsync方法,如BackgroundWorker等)。否则,主叫方应该等待它结束。

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

0

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

BackgroundWorkerThread会给你一个改变,取消任务,然后回复取消。

+0

使用并行计算有很多优点。 – Stacker 2011-06-01 13:31:57

+1

甚至在这里列出的优点太多了...检查出来。这就像从拨号调制解调器到宽带一样。一旦你这样做,你永远不会回去。 – BonanzaDriver 2011-06-02 06:15:32