2014-01-15 50 views
3

我正在启动一些关于.net中的异步编程的测试,现在我被困在尝试使用cancellationToken取消一个长操作。操作正在运行时的同步取消操作

所以我有以下代码:

CancellationTokenSource cancelationToken = new CancellationTokenSource(); 

我的按钮来启动操作

private void button2_Click(object sender, EventArgs e) 
    { 
     cancelationToken.Cancel(true); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     StartOperation(cancelationToken.Token); 
    } 

最后我的操作

private async void StartOperation(CancellationToken cancelToken) 
    { 
     await GetItensFromDatabase2(cancelToken); 
    } 

    public static Task<int> GetItensFromDatabase(CancellationToken cancelToken) 
    { 
     //cancelToken.Register(() => Console.WriteLine("Canceled")); 
     return Task.Factory.StartNew<int>(() => 
     { 
      int result = 0; 

      cancelToken.ThrowIfCancellationRequested(); 

      result = MyLongOperation(); // Simulates my operation -> I want to cancel while this operation is still running 

      return result; 

     }, cancelToken); 
    } 

那么,如何取消MyLongOperation()方法 ?有可能吗?

+0

对于'async'代码,请使用'Task.Run'而不是'StartNew'; [我解释了为什么在我的博客](http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html)。 –

+0

Task.Run不存在于.net 4中 – mmarques

+0

在'Microsoft.Bcl.Async'中,它是'TaskEx.Run'。 –

回答

5

不可能在任何点取消,的CancellationToken的目的是为了让用户在长时间运行的操作预期,取消操作,...

while(!finished) 
{ 
    cancelToken.ThrowIfCancellationRequested(); 
    //Some not cancelable operations 
} 

这里是一个比较常见的方法取消的方法

private static void LongRunning(CancellationToken cancelToken) 
{ 
    while (true) 
    { 
     if(cancelToken.IsCancellationRequested) 
     { 
      return; 
     } 
     //Not canceled, continue to work 
    } 
} 

想法是,该用户请求取消,但只有执行者决定何时停止他的工作。通常执行者在达到某个“安全点”后会取消

对于Abort长时间运行的操作并不是很好的尝试,而且询问了大量的帖子。

+0

你说的是我只能取消循环内的操作? ,如果我当前的执行点在if(cancelToken.IsCancellationRequested)之外并且用户想要取消,那么此时不允许取消对吗? – mmarques

+0

您可以运行循环线性代码,比if(cancelToken.IsCancellationRequested)返回更多;比其他代码,再次检查取消和... –

1

对于初学者来说,如果你已经运行了“cancelToken.ThrowIfCancellationRequested”这个逻辑,然后你取消了,那么你将会遇到一个问题。 “MyLongOperation”如何知道您已取消该任务? :)

取消长时间运行的任务,通常需要在的CancellationToken作为参数,使代码看起来是这样的:

// Check if cancelled 
// do work part 1 
// Check if cancelled 
// do work part 2 

的撤销操作的粒度是高达开发商。

+0

这是我害怕的aproach。谢谢 – mmarques