Я не уверен, что пойду об этом в правильном поместье, вот мой сценарий:
У меня есть веб-сайт MVC, который имеет представление фактурирования, состоящее из формы, в которой пользователь выбирает функцию из раскрывающегося списка и год / месяц из другого раскрывающегося списка. Нажатие на кнопку «Процесс» запускает сообщение для функции в моем контроллере.
Эта функция использовала данные, переданные для выполнения хранимой процедуры, и возвращает либо «SUCCESS», либо «FAIL», которые возвращаются из хранимой процедуры @ Output.
К сожалению, многие из процедур занимают много времени (некоторые могут занимать 25 минут) и неизменны время ожидания сообщения.
Поскольку я не очень обеспокоен тем, что Stored Proc возвращает SUCCESS или FAIL, потому что Stored Proc отправит результаты по электронной почте или сообщение об ошибке, я решил попробовать вызвать асинхронную функцию и выполнить щелчок и забыть.
Вот что у меня есть:
часть кода для нажатия кнопки, которая отправляет сообщение в функцию InvoiceProcess
var postURL = '@Url.Content("~/Invoicing/InvoiceProcess")'
$.ajax({
url: postURL,
type: "post",
data: {
ProcName: usp,
User: '@Model.FJLogin',
Email: '@Model.Email',
ParamName : paramName,
ParamValue: paramValue
},
success: function (r) {
if (r == "SUCCESS") {
invoiceNotification.show({
title: "Process acknowledged",
message: 'The Procedure acknowledged it has started. It may take a while to run. Results will be emailed to you as soon as the process has completed.'
}, "success");
} else {
invoiceNotification.show({
title: "Function Process Failed",
message: '<ul>' + r + '</ul>'
}, "error");
}
btnProc.prop("disabled", false);
}
});
Контроллер имеет следующее:
<HttpPost>
Function InvoiceProcess(ByVal ProcName As String, ByVal User As String, ByVal Email As String, ByVal ParamName As String, ByVal ParamValue As String) As String
' Problem - function is executing specified stored proc which can take a while to execute. (three of the procs typically takes 20-25mins).
' If the stored proc takes too long the ajax call that triggers this post can timeout giving the user an error when in fact there was no error... the page just timed out.
' Solution - have this method set a boolean Session variable (ProcName +'Triggered'). If it is false when this post method is called we asynchronously execute the required
'stored proc, else the method simply returns a message informing user that this proc has been triggered and is still running.
Dim mySessionName = ProcName & "Triggered"
If IsNothing(Session(mySessionName)) Then Session(mySessionName) = False
If Session(mySessionName) Then
Return "ERROR: This procedure has been triggered and is still being processed. Please wait for result."
Exit Function
Else
Dim logMsg As String = "The stored procedure " & ProcName & " was triggered by " & User & " - " & Email & " on " & Now().ToString & " with the following value '" & ParamValue & "' for the paramerter @" & ParamName & "."
LogMsgToLogFile(logMsg, "InvoiceProcess", "InvoiceController")
HostingEnvironment.QueueBackgroundWorkItem(Async Function(cancellationToken)
Await runStoredProcedure(ProcName, User, Email, ParamName, ParamValue)
Session(mySessionName) = False
End Function)
Session(mySessionName) = True
Return "SUCCESS"
End If
End Function '- Invoice Process
Private Function runStoredProcedure(ByVal ProcName As String, ByVal User As String, ByVal Email As String, ByVal ParamName As String, ByVal ParamValue As String) As Task(Of Object)
LogMsgToLogFile("Process triggered off")
'Dim Result As String = DBFunctions.ExecuteStoredProc(ProcName, User, Email, ParamName, ParamValue)
'Set up SqlConnection
Dim strConnString As String = ConfigurationManager.ConnectionStrings("FADConn").ConnectionString
Dim con As New SqlConnection(strConnString)
Dim cmd As New SqlCommand With {
.CommandType = Data.CommandType.Text
}
Dim SqlScript = "EXEC dbo." & ProcName & " @User = '" & User & "', @EmailAddress = '" & Email & "'"
If ParamName <> "" Then
SqlScript += ", @" & ParamName & " = " & ParamValue
End If
SqlScript += ";"
cmd.CommandText = SqlScript
cmd.Connection = con
Try
con.Open()
cmd.ExecuteNonQuery()
Return Nothing
Catch ex As Exception
Dim msg As String = "<li>" & ex.Message & "</li>"
If Not IsNothing(ex.InnerException) Then
msg += "<ul><li>" & ex.InnerException.Message & "</li></ul>"
End If
LogExceptionToLogFile("DBFunctions", "ExecuteStoredProc", ex)
Return Nothing
Finally
con.Close()
con.Dispose()
End Try
LogMsgToLogFile("Process finished")
'Return Nothing
End Function ' runStoredProcedure
При запуске функция LogMsgToLogFile завершается нормально.
Но HostingEnvironment.QueueBackgroundWorkItem (асинхронная функция (cancellationToken)
...
) не запускается .... не выполняется ни один из LogMsgToLogFile в функции runStoreProcedure. Любые точки останова в этой функции когда-либо получают удар. Хранимые Procs все в порядке, когда запускаются непосредственно из SQL. Кроме того, с веб-сайта все работало нормально, когда у меня был код, выполняющий сохраненный процесс в функции Post без использования функции Async.
Любая помощь приветствуется.