這是一個vb.net mvc 3應用程序..我是新來的異步和線程組合,所以這是有點在我的頭上2級...我有一個長時間運行的過程,發送大量電子郵件在設定的時間間隔,以避免違反使用條款..不僅對於這個任務,但對於其他選項,我想添加一個進度條,通過java更新..我發現了一個博客文章做這樣的事情...我已經得到了下面的代碼,但似乎有在進度條從不說明一個問題......異步進度欄更新
下面是我的extendedTaskRun類:
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading
Namespace ExtendedTaskHandler
''' <summary>
''' Long Running Test Class.
''' </summary>
Public Class extendedTaskRun
Private Shared syncRoot As New Object()
''' <summary>
''' Gets or sets the process status.
''' </summary>
''' <value>The process status.</value>
Private Shared Property ProcessStatus() As IDictionary(Of String, Integer)
Get
Return m_ProcessStatus
End Get
Set(value As IDictionary(Of String, Integer))
m_ProcessStatus = value
End Set
End Property
Private Shared m_ProcessStatus As IDictionary(Of String, Integer)
''' <summary>
''' Initializes a new instance of the <see cref="extendedTaskRun"/> class.
''' </summary>
Public Sub New()
If ProcessStatus Is Nothing Then
ProcessStatus = New Dictionary(Of String, Integer)()
End If
End Sub
Public Sub SetStatus(ByVal id As String, ByVal value As Integer)
SyncLock syncRoot
ProcessStatus(id) = value
End SyncLock
End Sub
''' <summary>
''' Processes the long running action.
''' </summary>
''' <param name="id">The id.</param>
Public Function ProcessLongRunningAction(id As String) As String
For i As Integer = 1 To 100
Thread.Sleep(100)
SyncLock syncRoot
ProcessStatus(id) = i
End SyncLock
Next
Return id
End Function
''' <summary>
''' Adds the specified id.
''' </summary>
''' <param name="id">The id.</param>
Public Sub Add(id As String)
SyncLock syncRoot
ProcessStatus.Add(id, 0)
End SyncLock
End Sub
''' <summary>
''' Removes the specified id.
''' </summary>
''' <param name="id">The id.</param>
Public Sub Remove(id As String)
SyncLock syncRoot
ProcessStatus.Remove(id)
End SyncLock
End Sub
''' <summary>
''' Gets the status.
''' </summary>
''' <param name="id">The id.</param>
Public Function GetStatus(id As String) As Integer
SyncLock syncRoot
If ProcessStatus.Keys.Where(Function(x) x = id).Count = 1 Then
Return ProcessStatus(id)
Else
Return 100
End If
End SyncLock
End Function
End Class
End Namespace
然後我的控制器如下:
Public Function MassEmailStatus() As ActionResult
MassEmailAddressList = TempData("emailaddresses")
TempData.Clear()
TempData.Add("emailaddresses", MassEmailAddressList)
Return View()
End Function
Public Function MassEmailSendingStatus(ByVal id As String) As ActionResult
Dim d As List(Of String) = TempData("emList")
Dim EmailCount As Integer = d.Count
Dim triedCount As Integer = 0
Dim extendedTaskRun As New extendedTaskRun
extendedTaskRun.Add(id)
Dim percentDone As Integer = 0
While Not (triedCount = EmailCount)
For Each em In d
EmailSender(em, String.Empty)
triedCount += 1
percentDone = EmailCount/100 + triedCount
extendedTaskRun.SetStatus(id, percentDone)
Next
End While
extendedTaskRun.Remove(id)
Return View()
End Function
然後MassEmailStatus觀點如下:
@Code
ViewData("Title") = "MassEmailSendingStatus"
TempData.Add("emList", TempData("emailaddresses"))
end Code
<div>
<a href="#" id="startProcess">Start Long Running Process</a>
</div>
<br />
<div id="statusBorder">
<div id="statusFill">
</div>
</div>
<script type="text/javascript">
var uniqueId = '@Guid.NewGuid().ToString()';
var tdata = '@TempData("emailaddresses")';
$(document).ready(function (event) {
$('#startProcess').click(function() {
$.post("MassEmailSendingStatus", { id: uniqueId }, function() {
$('#statusBorder').show();
getStatus();
});
event.preventDefault;
});
});
function getStatus() {
var url = 'Admin/GetCurrentProgress/' + uniqueId;
$.get(url, function (data) {
if (data != "100") {
$('#status').html(data);
$('#statusFill').width(data);
window.setTimeout("getStatus()", 100);
}
else {
$('#status').html("Done");
$('#statusBorder').hide();
alert("The Long process has finished");
};
});
}
</script>
這些都是在博客中提到,並在我的代碼,但是從看代碼的附加功能我知道他們無法正確接線。
Private Delegate Function ProcessTask(id As String) As String
Private extendedRunClass As New extendedTaskRun
''' <summary>
''' Starts the long running process.
''' </summary>
''' <param name="id">The id.</param>
Public Sub StartLongRunningProcess(id As String)
extendedRunClass.Add(id)
Dim processTask As New ProcessTask(AddressOf extendedRunClass.ProcessLongRunningAction)
processTask.BeginInvoke(id, New AsyncCallback(AddressOf EndLongRunningProcess), processTask)
End Sub
''' <summary>
''' Ends the long running process.
''' </summary>
''' <param name="result">The result.</param>
Public Sub EndLongRunningProcess(result As IAsyncResult)
Dim processTask As ProcessTask = DirectCast(result.AsyncState, ProcessTask)
Dim id As String = processTask.EndInvoke(result)
extendedRunClass.Remove(id)
End Sub
''' <summary>
''' Gets the current progress.
''' </summary>
''' <param name="id">The id.</param>
Public Function GetCurrentProgress(id As String) As ContentResult
Me.ControllerContext.HttpContext.Response.AddHeader("cache-control", "no-cache")
Dim currentProgress = extendedRunClass.GetStatus(id).ToString()
Return Content(currentProgress)
End Function
我知道我不是真正啓動過程,我只是呼籲EmailSender(em, String.Empty)
這是在工作時,裏面的MassEmailSendingStatus控制器的每個循環......我必須做什麼才能正確解決這一問題?