2016-08-19 3 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

안녕하세요. Scott. on .Net 4. .net을 업데이트하고 해당 항목이 다운 스트림에 영향을 미치는지 확인합니다. 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