取消方法执行的正确方法



可能的重复项:
如何中止/取消 TPL 任务?

我有一个需要一些时间来执行的方法,因此我将结果作为回调返回。我的方法如下所示:

public static void DoWork( Action<object> onCompleteCallBack)
{
  Task.Factory.StartNew( () => {
    // Do work
    onCompleteCallBack(someResult);
  });
}

现在我希望能够在用户不想等待的情况下停止执行该方法。结果,这就是我所解决的:

static void Main ( string[] args )
{            
  var cancelMethod = DoWork( x =>
  {                
    // method completed
    Console.Write( x.ToString() );
  });
  Thread.Sleep( 5000 ); // some time passes 
  // then user decides to abort method
  cancelMethod();
  Console.Read();
}
static Action DoWork ( Action<object> onCompleteCallBack )
{
  bool stopExecuting = false;
  Task.Factory.StartNew( () =>
  {
    for ( var i = 0 ; i < 100000 ; i++ ) 
    {
      Thread.Sleep( 1 );
      if ( stopExecuting )
      {
        onCompleteCallBack( "Method aborted!" );
        return;
      }
    }         
    onCompleteCallBack( "Method completed successfully" );
  } );
  return () => { stopExecuting = true; };
}
中止方法

执行的更合适方法是什么?

编辑

感谢您的回答。我现在记得关于取消令牌的事情。令牌的事情很难记住。我想我会使用这种方法:

    static void Main ( string[ ] args )
    {
        Action abortTask;
        DoWork( methodCompleted, out abortTask );
        Thread.Sleep( 5000 ); // some time passes then user decides to abort method
        // cancel execution of method
        abortTask( );
        Console.Read( );
    }
    static void methodCompleted ( object msg )
    {            
        Console.Write( msg.ToString( ) );  
    }
    static void DoWork ( Action<object> onCompleteCallBack, out Action abortThisTask )
    {
        bool stopExecuting = false;
        abortThisTask = ( ) => { stopExecuting = true; };
        Task.Factory.StartNew( ( ) =>
        {
            for ( var i = 0 ; i < 100000 ; i++ ) 
            {
                Thread.Sleep( 1 );
                if ( stopExecuting )
                {
                    onCompleteCallBack( "Method aborted!" );
                    return;
                }
            }
            onCompleteCallBack( "Method completed successfully" );
        } );            
    }
    // Overloaded method
    static void DoWork ( Action<object> onCompleteCallBack )
    {
        Action abortTask;
        DoWork( onCompleteCallBack ,out abortTask );
    }

使用你们在回答这个问题时建议的方法与这种方法会更好吗?我更喜欢这种方法。我认为它比取消令牌更容易阅读。

附言。我的Visual Studio放置了很多空间。随意格式化代码:)

尝试使用取消令牌,方法是在任务中指定您的函数http://blogs.msdn.com/b/csharpfaq/archive/2010/07/19/parallel-programming-task-cancellation.aspx

CancellationTokenSource tokenSource = new CancellationTokenSource();
 Task.Factory.StartNew( () => {
    // Do work
    onCompleteCallBack(someResult);
  }, tokenSource.Token);
private void cancel_Click(object sender, RoutedEventArgs e)
{
    tokenSource.Cancel();
}
查看 CancelToken

和 Albahari 的安全取消线程指南

接受 CancelToken 的 StartNew() 方法存在重载。下面是一个示例:http://msdn.microsoft.com/en-us/library/dd997396.aspx。基础知识是创建此令牌,然后将其传递给方法(或从父线程引用它;它是线程安全的)。然后,您的并行方法必须在方便的时间(例如在循环中)检查令牌是否指示任务已被取消。如果是这样,它将优雅地退出。

任务允许您传入CancellationToken .你可以打电话给ct。取消() 为了设置取消标志。 在实际的执行逻辑中,您可以在某些"检查点"添加检查,这些检查点测试if (ct.IsCancellationRequested)并从那里返回方法,或者调用ct.ThrowIfCancellationRequested()

http://msdn.microsoft.com/en-us/library/dd537607(v=vs.100).aspx可能是一个很好的起点。取决于你要做什么。

最新更新