7

重複の可能性:
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 );
    }

この質問に対する回答で提案されたアプローチと、このアプローチを使用する方が良いでしょうか。私はこのアプローチの方が好きです。キャンセルトークンの方が読みやすいと思います。

PS。私の Visual Studio は多くのスペースを配置します。コードを自由にフォーマットしてください:)

4

5 に答える 5

4

タスクで関数を指定してキャンセル トークンを使用してみてください 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();

}
于 2012-11-20T22:05:27.430 に答える
1

CancellationTokenAlbahariのスレッドを安全にキャンセルするためのガイドをご覧ください

于 2012-11-20T22:01:51.533 に答える
1

CancellationTokenを受け入れるStartNew()メソッドのオーバーロードがあります。次に例を示します:http://msdn.microsoft.com/en-us/library/dd997396.aspx。基本は、このトークンを作成してメソッドに渡すことです(または、親スレッドから参照します。スレッドセーフです)。次に、並列メソッドは、都合のよいときに(ループ内など)、トークンがタスクがキャンセルされたことを示しているかどうかを確認する必要があります。もしそうなら、それは優雅に終了します。

于 2012-11-20T22:02:05.697 に答える
1

タスクを使用すると、CancellationToken. キャンセルのフラグを設定するために ct.Cancel() を呼び出すことができます。実際の実行ロジック内で、特定の「チェックポイント」でチェックを追加してif (ct.IsCancellationRequested)、そこからメソッドをテストして返すか、代わりに を呼び出すことができますct.ThrowIfCancellationRequested()

于 2012-11-20T22:05:14.297 に答える
0

http://msdn.microsoft.com/en-us/library/dd537607(v=vs.100).aspxから始めるのがよいでしょう。あなたが何をしようとしているのかに応じて。

于 2012-11-20T22:00:11.677 に答える