6.2.5.1 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のネームスペース
-
このMicrosoft .NET Framework 機能の詳細は、
http://msdn.microsoft.com/library
を参照