C# 取消方法执行的正确方法

C# 取消方法执行的正确方法,c#,task-parallel-library,abort,cancellation,C#,Task Parallel Library,Abort,Cancellation,可能重复: 我有一个需要一些时间来执行的方法,因此我将结果作为回调返回。我的方法如下所示: public static void DoWork( Action<object> onCompleteCallBack) { Task.Factory.StartNew( () => { // Do work onCompleteCallBack(someResult); }); } publicstaticvoiddowork(操作onCompleteCa

可能重复:

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

public static void DoWork( Action<object> onCompleteCallBack)
{
  Task.Factory.StartNew( () => {
    // Do work
    onCompleteCallBack(someResult);
  });
}
publicstaticvoiddowork(操作onCompleteCallBack)
{
Task.Factory.StartNew(()=>{
//工作
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(字符串[]args)
{            
var cancelMethod=DoWork(x=>
{                
//方法完成
Console.Write(x.ToString());
});
Thread.Sleep(5000);//有些时间过去了
//然后用户决定中止该方法
取消方法();
Console.Read();
}
静态操作DoWork(操作onCompleteCallBack)
{
bool-stopExecuting=false;
Task.Factory.StartNew(()=>
{
对于(变量i=0;i<100000;i++)
{
睡眠(1);
如果(停止执行)
{
onCompleteCallBack(“方法中止!”);
返回;
}
}         
onCompleteCallBack(“方法成功完成”);
} );
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 );
    }
static void Main(字符串[]args)
{
行动中止任务;
DoWork(方法完成,任务终止);
Sleep(5000);//过了一段时间,用户决定中止该方法
//取消方法的执行
abortTask();
Console.Read();
}
静态无效方法已完成(对象消息)
{            
Write(msg.ToString());
}
静态无效DoWork(操作onCompleteCallBack,输出操作AbortHistTask)
{
bool-stopExecuting=false;
AbortHistTask=()=>{stopExecuting=true;};
Task.Factory.StartNew(()=>
{
对于(变量i=0;i<100000;i++)
{
睡眠(1);
如果(停止执行)
{
onCompleteCallBack(“方法中止!”);
返回;
}
}
onCompleteCallBack(“方法成功完成”);
} );            
}
//重载方法
静态void DoWork(操作onCompleteCallBack)
{
行动中止任务;
DoWork(未完成回调,退出中止任务);
}
使用你们在回答这个问题时建议的方法与使用这种方法相比会更好吗。我更喜欢这种方法。我认为它比取消令牌更容易阅读

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

可能是一个很好的开始。取决于您的目的。

查看并安全地取消线程

存在接受CancellationToken的StartNew()方法的重载。下面是一个例子:。最基本的是您创建并将这个令牌传递给您的方法(或者从父线程引用它;它是线程安全的)。然后,您的并行方法必须在方便的时候(比如在循环中)检查令牌是否指示任务已取消。如果是这样,它将优雅地退出。

任务允许您传入一个
CancellationToken
。您可以调用ct.Cancel()来设置取消标志。在实际执行逻辑中,您可以在某些“检查点”添加检查,这些检查点测试
if(ct.IsCancellationRequested)
并从那里返回方法,或者调用
ct.throwifccancellationrequested()

通过在任务中指定函数来尝试使用取消令牌


OP未直接使用线程。否。Thread.Abort()是邪恶的。是的,我粘贴了错误的MSDN文章的URL。愚蠢的我。谢谢你的链接,我将尝试关闭我的答案,这正是我所寻找的。通过取消安装请求的
有什么意义?我知道这种方法来自MSDN,但为什么不直接抛出New
UserCancellationException
或任何适用的方法呢?我不太确定,因为我自己对这种方法很陌生;我只是在分享我学到的东西。就个人而言,我只是返回一些不同的东西,而不是抛出异常。一般来说,抛出异常的好处是在异常处理程序中有清理逻辑。我也在学习,但从未听说过throwifcancellationrequest
。如果你解释它能带来的好处,特别是在MSDN上描述的上下文方面,我个人会给你这个答案加1分。:)这很有趣。如果(token.IsCancellationRequested)抛出新操作CanceledException(token),则看起来像是
ThrowifcCancellationRequested
=
if(token.IsCancellationRequested)抛出新操作CanceledException(token)
即使后者更具可读性,也就是说,您可以清楚地看到抛出的异常类型。在我看来,
OperationCanceledException
UserCancellationException
之间的区别在于它们派生的类以及它们的用途。根据MSDN文档,当用户在GetToken(CardSpacePolicyElement[],SecurityTokenSerializer)调用期间取消操作时,会引发
UserCancellationException
该方法位于
System.IdentityModel.Selectors
命名空间中,而
OperationCanceledException
派生自
System.Exception
,还包含已取消的原始
CancellationToken
CancellationTokenSource tokenSource = new CancellationTokenSource();
 Task.Factory.StartNew( () => {
    // Do work
    onCompleteCallBack(someResult);
  }, tokenSource.Token);

private void cancel_Click(object sender, RoutedEventArgs e)
{
    tokenSource.Cancel();

}