2016-08-19 2 views
0

私のチームと私は一週間中この周りに頭を叩いています。助けをお待ちしています。私たちはVB.Netを使用しています。私たちは、ユーザーがSQLCommandを使用して実行するのに数分かかるストアドプロシージャを実行するフォームを持っています。ユーザーは、実行中にアプリケーションで作業を続けたり、処理の途中でリクエストを取り消したりできるようにしたいと考えています。我々は、スレッドとバックグラウンドワーカー、および非同期処理について検討しました。ストアドプロシージャの実行をキャンセルし、エラーなく安全にスレッドを実行できるソリューションを見つけることはできません。誰でもこれを安全に行う方法を知っていますか?これまでのところこれがあります。セキュリティとサイズのために一部の詳細が削除されました.Netを実行する方法:SQLCommandは、ユーザーが安全に途中でキャンセルできるようにする独自のスレッドです

Private Sub frmAdhocRptGenerator_Load(sender As Object, e As EventArgs) Handles Me.Load 
    BackGroundWorkerAdhoc.WorkerReportsProgress = True 
    BackGroundWorkerAdhoc.WorkerSupportsCancellation = True 
End Sub 

Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click 
     If Not BackGroundWorkerAdhoc.IsBusy = True Then BackGroundWorkerAdhoc.RunWorkerAsync() 
End Sub 

Private Sub BackGroundWorkerAdhoc_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackGroundWorkerAdhoc.DoWork 
    Try 
     If BackGroundWorkerAdhoc.CancellationPending = True Then 
      e.Cancel = True 
      Exit Sub 
     End If 
     Load_n_ExecuteProc(tmpConn) 
    Catch ex As Exception 
     ErrorHandler("frmAdhocRptGenerator.subBackGroundWorkerAdhoc_DoWork", ex.ToString) 
     tmpConn.Close() 
    End Try 
End Sub 

Private Function Load_n_ExecuteProc(theConn As SqlConnection) As Boolean 
    If BackGroundWorkerAdhoc.CancellationPending = True Then 
     Return False 
     Exit Function 
    End If 
    Try 
     Dim RunCompleted As Boolean = False 

     cmdPROVIDER_FINDER = New SqlCommand("SP$PROVIDER_FINDER", tmpConn) 
       cmdPROVIDER_FINDER.CommandType = CommandType.StoredProcedure 
       cmdPROVIDER_FINDER.CommandTimeout = 10000 
       Dim rst As Integer = cmdPROVIDER_FINDER.ExecuteNonQuery() 
       RunCompleted = rst > -1 
     Return RunCompleted 
    Catch ex As Exception 
     ErrorHandler("frmAdhocRptGenerator.Load_n_ExecuteProc", ex.ToString) 
     Return False 
    End Try 
End Function 


Private Sub BackGroundWorkerAdhoc_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackGroundWorkerAdhoc.RunWorkerCompleted 
    Try 
     If Success = True Then 
      Dim filename As String = "AdhocResults" & Now.Month.ToString & "-" & Now.Day.ToString & "-" & Now.Year.ToString 
      Export2Excel("SELECT * FROM ##PF_PROVIDERS" & currUser.UserID, filename, True) 
     End If 
     tmpConn.Close() 
     Success = False 
    Catch ex As Exception 
     ErrorHandler("frmAdhocRptGenerator.BackGroundWorkerAdhoc_RunWorkerCompleted", ex.ToString) 
    Finally 
     tmpConn.Close() 
    End Try 
End Sub 


Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click 
    If BackGroundWorkerAdhoc.IsBusy = True Then 
     BackGroundWorkerAdhoc.CancelAsync() 
     cmdPROVIDER_FINDER.Cancel() 
     tmpConn.Close() 
     tmpConn = Nothing 
    End If 
    btnCancel.Enabled = False 
End Sub 
+0

あなたの現在の実装で直面しているエラー/望ましくない動作は何ですか? –

+0

.NET 4.5以降を使用していますか?もし 'ExecuteNonQueryAsync'を呼び出してCancellationTokenを渡すことができれば、バックグラウンドワーカーの代わりにasync/awaitを使うことができるので、リクエストを取り消すこともできます。 –

+0

こんにちはスコット、ネット上にいた。私は、ネットを更新して、それが何かダウンストリームに影響を与えるかどうか調べ始めるだろう。 Alex、エラーは「現在のコマンドで重大なエラーが発生しました」またはタイムアウトエラーです。コマンドをキャンセルすると私には表示されませんが、プロシージャが実行されたかキャンセルされたことをbgworkerに伝え、タイムアウトまで待機し続けます。 – AdeodatusX

答えて

0

バックグラウンドワーカーのキャンセルは魔法の方法ではありません。それは、.CancellationPendingがtrueに設定されているだけです。コードを実際に安全に実行し、DoWorkハンドラを終了するのはあなたのコード次第です。

既存のキャンセルコードは、スレッドが開始される前にユーザーがキャンセルした場合にのみ機能します。そうしないと、削除することはできません。

If BackGroundWorkerAdhoc.CancellationPending = True Then 
    Return False 
    Exit Function 
End If 

代わりに、UIスレッドからSqlCommand.Cancel呼び出しを発行します。コマンドが終了するとDoWorkが正常に終了します。 SQLコマンドを途中で終了させるつもりならば、SqlConnectionを投げ捨てることをお勧めします。なぜ新しいものを作成したのですか?

Private Sub BackGroundWorkerAdhoc_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackGroundWorkerAdhoc.DoWork 
    Try 
     Using myNewConn As New SqlConnection(...) 
      Load_n_ExecuteProc(myNewConn) 
     End Using 
    Catch ex As Exception 
     ErrorHandler("frmAdhocRptGenerator.subBackGroundWorkerAdhoc_DoWork", ex.ToString) 
    End Try 
End Sub 

Private Function Load_n_ExecuteProc(theConn As SqlConnection) As Boolean 
    Try 
     cmdPROVIDER_FINDER = New SqlCommand("SP$PROVIDER_FINDER", tmpConn) 
     cmdPROVIDER_FINDER.CommandType = CommandType.StoredProcedure 
     cmdPROVIDER_FINDER.CommandTimeout = 10000 
     Dim rst As Integer = cmdPROVIDER_FINDER.ExecuteNonQuery() 
     return = rst > -1 
    Catch ex As Exception 
     ErrorHandler("frmAdhocRptGenerator.Load_n_ExecuteProc", ex.ToString)    
    Finally 
     cmdPROVIDER_FINDER = Nothing 
    End Try 
End Function 

Public Sub CancelSqlCommand() 
    Dim cmd = cmdPROVIDER_FINDER 
    If cmd isnot Nothing cmd.Cancel() 
End Sub 
関連する問題