プライマリ・コンテンツに移動

Oracle® Data Provider for .NET開発者ガイド ODAC 12.2c リリース1 (12.2.0.1) for Microsoft Windows E88311-03 |
| 目次 | 索引

前 | 次 |

# Cancel

このメソッドは、特定の接続で現在実行されているコマンドの取消しを試みます。

宣言

    // C#
    public override void Cancel();

実装

`IDbCommand.Cancel`

備考

コマンドが正しく取り消された場合は、例外がスローされます。正しく取り消されない場合、例外はスローされません。`Cancel`の起動時に実行中のコマンドがない場合、`Cancel`は何も実行しません。`Cancel`メソッドを起動しても、その時点で実行されているコマンドが常に取り消されることが保証されるわけではありません。実行が終了する前にその実行が完了する場合があります。このような場合、例外はスローされません。

複数の`OracleCommand`オブジェクトが同じ接続を共有する場合、その接続上の一時点で実行できるコマンドは1つのみです。`Cancel`メソッドは、起動されると、`OracleCommand`オブジェクトがコマンドの実行に使用している接続上で現在実行されている文を取り消そうとします。ただし、複数の`OracleCommand`オブジェクトが同じ接続上で同時に文を実行している場合は、`Cancel`メソッドを起動すると、発行済のコマンドが取り消される可能性があります。これは、`Cancel`の起動が有効になる前に取消を指示したコマンドが完了する可能性があるためです。これが発生した場合、別の`OracleCommand`によって実行されるコマンドが、かわりに取り消される可能性があります。

`Cancel`メソッドが原因となるこの不確定な状況を回避するには、次のようないくつかの方法があります。

- アプリケーションで各接続に`OracleCommand`オブジェクトを1つのみ作成できます。これにより、特定の接続を使用する`OracleCommand`オブジェクトで実行されるコマンドのみが、`Cancel`の起動によって確実に取り消されます。

- アプリケーション内でのコマンドの実行は、同じ接続を使用する`OracleCommand`オブジェクト間で同期化することができます。

`Cancel`がアプリケーションで使用されない場合、前述の内容は適用されません。

現在の実行がいつ終了するかは不明確であるため、非原子的なSQLまたはPL/SQLの実行はトランザクション内で開始することをお薦めします。コマンドの実行が例外`ORA-01013:` `user` `requested` `cancel` `of` `current` `operation`で正しく終了した場合、トランザクションをロールバックしてデータの整合性を保つことができます。コマンドの取消が発生した場合、他の例外として`ORA-00936`および`ORA-00604`がスローされることがあります。非原子的な実行の例としては、1つずつ実行されるDMLコマンドのコレクションや、PL/SQLのストアド・プロシージャまたは関数の一部である複数のDMLコマンドなどがあります。

例

    // C#

    // This example shows how command executions can be cancelled in a
    // deterministic way even if multiple commands are executed on a single
    // connection.  This is accomplished by synchronizing threads through events.
    // Since the Cancel method terminates the currently running operation on the
    // connection, threads must be serialized if multiple threads are using the
    // same connection to execute server round-trip incurring operations.
    // Furthermore, the example shows how the execution and cancel threads should
    // be synchronized so that nth iteration of the command execution does not
    // inappropriately cancel the (n+1)th command executed by the same thread.

    using System;
    using System.Data;
    using Oracle.DataAccess.Client;
    using System.Threading;

    class CancelSample
    {
      private OracleCommand cmd;
      Thread t1, t2;
      // threads signal following events when assigned operations are completed

      private AutoResetEvent ExecuteEvent = new AutoResetEvent(false);
      private AutoResetEvent CancelEvent = new AutoResetEvent(false);
      private AutoResetEvent FinishedEvent = new AutoResetEvent(false);
      AutoResetEvent[] ExecuteAndCancel = new AutoResetEvent[2];

      // Default constructor
      CancelSample()
      {
        cmd = new OracleCommand("select * from all_objects",
          new OracleConnection("user id=scott;password=tiger;data source=oracle"));
        ExecuteAndCancel[0] = ExecuteEvent;
        ExecuteAndCancel[1] = CancelEvent;
      }

      // Constructor that takes a particular command and connection
      CancelSample(string command, OracleConnection con)
      {
        cmd = new OracleCommand(command, con);
        ExecuteAndCancel[0] = ExecuteEvent;
        ExecuteAndCancel[1] = CancelEvent;
      }

      // Execution of the command
      public void Execute()
      {
        OracleDataReader reader = null;
        try
        {
          Console.WriteLine("Execute.");
          reader = cmd.ExecuteReader();
          Console.WriteLine("Execute Done.");
          reader.Close();
        }
        catch(Exception e)
        {
          Console.WriteLine("The command has been cancelled.", e.Message);
        }
        Console.WriteLine("ExecuteEvent.Set()");
        ExecuteEvent.Set();
      }

      // Canceling of the command
      public void Cancel()
      {
        try
        {
          // cancel query if it takes longer than 100 ms to finish execution
          System.Threading.Thread.Sleep(100);
          Console.WriteLine("Cancel.");
          cmd.Cancel();
        }
        catch (Exception e)
        {
          Console.WriteLine(e.ToString());
        }
        Console.WriteLine("Cancel done.");
        Console.WriteLine("CancelEvent.Set()");
        CancelEvent.Set();
      }

      // Execution of the command with a potential of cancelling
      public void ExecuteWithinLimitedTime()
      {
        for (int i = 0; i < 5; i++)
        {
          Monitor.Enter(typeof(CancelSample));
          try
          {
            Console.WriteLine("Executing " + this.cmd.CommandText);
            ExecuteEvent.Reset();
            CancelEvent.Reset();
            t1 = new Thread(new ThreadStart(this.Execute));
            t2 = new Thread(new ThreadStart(this.Cancel));
            t1.Start();
            t2.Start();
          }
          finally
          {
            WaitHandle.WaitAll(ExecuteAndCancel);
            Monitor.Exit(typeof(CancelSample));
          }
        }
        FinishedEvent.Set();
      }
      [MTAThread]
      static void Main()
      {
        try
        {
          AutoResetEvent[] ExecutionCompleteEvents = new AutoResetEvent[3];

          // Create the connection that is to be used by three commands
          OracleConnection con = new OracleConnection("user id=scott;" +
            "password=tiger;data source=oracle");
          con.Open();

          // Create instances of CancelSample class
          CancelSample test1 = new CancelSample("select * from all_objects", con);
          CancelSample test2 = new CancelSample("select * from all_objects, emp",
                                                con);
          CancelSample test3 = new CancelSample("select * from all_objects, dept",
                                                con);

          // Create threads for each CancelSample object instance
          Thread t1 = new Thread(new ThreadStart(test1.ExecuteWithinLimitedTime));
          Thread t2 = new Thread(new ThreadStart(test2.ExecuteWithinLimitedTime));
          Thread t3 = new Thread(new ThreadStart(test3.ExecuteWithinLimitedTime));

          // Obtain a handle to an event from each object
          ExecutionCompleteEvents[0] = test1.FinishedEvent;
          ExecutionCompleteEvents[1] = test2.FinishedEvent;
          ExecutionCompleteEvents[2] = test3.FinishedEvent;

          // Start all threads to execute three commands using a single connection
          t1.Start();
          t2.Start();
          t3.Start();

          // Wait for all three commands to finish executing/canceling before
          //closing the connection
          WaitHandle.WaitAll(ExecutionCompleteEvents);
          con.Close();
        }
        catch (Exception e)
        {
          Console.WriteLine(e.ToString());
        }
      }
    }

関連項目:

- Oracle.DataAccess.ClientおよびOracle.ManagedDataAccess.Clientのネームスペース

- OracleCommandクラス

- OracleCommandメンバー

- このMicrosoft .NET Framework 機能の詳細は、`http://msdn.microsoft.com/library`を参照