异步进度条更新

时间:2013-02-23 21:46:28

标签: vb.net multithreading asp.net-mvc-3 asynchronous

这是一个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控制器的每个循环内...我该怎么做才能正确解决这个问题?

1 个答案:

答案 0 :(得分:0)

WOW我的代码被破坏了...在获取博客代码并将其放入自己的快速项目并启动它后,我能够看到发生了什么......我现在正在使用它......我会更新这与工作解决方案有点...现在返回不仅仅是百分比到进度条,所以消息显示为工作..不知道我将如何做到这一点,但我想我会在getCurrentProgress内做方法作为字符串从extendedTaskRun类返回...