【问题标题】:Tracking elapsed time for a set of Tasks跟踪一组任务的经过时间
【发布时间】:2014-12-04 21:52:24
【问题描述】:

我正在尝试编写一个小型 VB.NET 应用程序,以便在工作中进行跨团队运动研究。我需要能够为单个任务运行多个计时器,当用户完成他们的任务时,他们可以结束它,它将存储在一个 CSV 文件中。我可以一次完成单个任务,这已经在业务中运行了一段时间。一次运行多任务的最佳方法是什么。我有将任务添加到列表视图并将双击事件作为结束任务功能的想法。但是我似乎无法让计时器独立运行。任何人都可以帮忙吗?这有意义吗?

这是本课程的主要工作量。如果这没有意义,我提前道歉。我不是一个专业的程序员,这只是我在工作中练习的一个业余爱好。

另一件事是实时计算经过的秒数,我可以用标签做到这一点,但理论上我需要无限量的任务......

Public Class runningTask
    Dim timenow As DateTime = Now
    Dim elapsed
    Dim localTask = GlobalVars.task

    Public Sub AddItem()
        CreateTimer()

        Dim str(3) As String
        Dim itm As ListViewItem

        str(0) = localTask
        str(1) = timenow
        str(2) = elapsed

        itm = New ListViewItem(str)

        frmTime.lvTimers.Items.Add(itm)
    End Sub

    Private Sub CreateTimer()
        Dim tmr As New Timer
        tmr.Interval = 1000
        tmr.Enabled = True
        AddHandler tmr.Tick, AddressOf GlobalTimerTick
    End Sub

    Private Sub GlobalTimerTick(ByVal sender As Object, ByVal e As EventArgs)
        Dim t As TimeSpan = Now - timenow
        elapsed = String.Format("{0:00}:{1:00}:{2:00}:{3:00}", Math.Floor(t.TotalHours), t.Minutes, t.Seconds, t.Milliseconds)
    End Sub

End Class

【问题讨论】:

    标签: vb.net timer stopwatch elapsedtime


    【解决方案1】:

    我采用了一种更 OOP 的方法,就 Timers 而言可能更经济,但界面非常简单。核心是一个跟踪作业和时间的TaskItem,然后是一个集合类来公开它们、启动它们和停止它们。通过将尽可能多的功能隐藏在尽可能低的级别,事情会变得更简单。

    我只使用了一个计时器,但不明白为什么您需要多个计时器来完成一项任务。如果 TaskItem 在启动时记录了DateTime(这在我的创建时会自动发生),那么您根本不需要任何计时器。 Elapsed 始终使用StartedTime 和DateTime.Now(用于正在运行的任务)或CompletedTime 用于已完成的任务来计算。我看不到 Timer 在哪里添加了任何东西。

    您必须为自己的目的制作许多模组。这不会保存已完成的项目,也不会从列表中删除它们,但可能会给您一个开始的地方。这也是第一次通过的事情;这里和那里肯定有问题。

    Imports System.Collections.ObjectModel
    
    Public Class Tasks
    
        ' slight overkill
        Private Enum LVGroups
            Running
            Completed
        End Enum
    
        Public Enum TaskJobs
            SweepFloor
            BuildRobot
            CleanOven
            RepairRobot
            EmptyTrash
            TeachRobotToTalk
            MakeCoffee
            TeachRobotToWalk
            WashDishes
            TeachRobotVisualBasic
        End Enum
    
        ' class for a single task
        Public Class TaskItem
            ' these ought to be readonly; so no cheating
            Public Property ID As String
            Public Property EmpName As String
    
            Public Property StartedTime As DateTime
            Public Property CompletedTime As DateTime
    
            ' or job code...
            Public Property Job As TaskJobs
    
            ' put in a ClassLib or Namespace
            Friend Sub New(sName As String, tj As TaskJobs)
                EmpName = sName
                Job = tj
    
                StartedTime = DateTime.Now
                CompletedTime = DateTime.MaxValue
                ID = System.Guid.NewGuid.ToString
            End Sub
    
            Public Function IsActive() As Boolean
                Return (CompletedTime = DateTime.MaxValue)
            End Function
    
            Public Sub EndTask()
                CompletedTime = DateTime.Now
            End Sub
    
            Public Function GetElapsed() As String
                Dim t As TimeSpan
                If IsActive() Then
                    t = DateTime.Now - StartedTime
                Else
                    t = CompletedTime - StartedTime
                End If
                Return String.Format("{0:00}:{1:00}:{2:00}", Math.Floor(t.TotalHours),
                                                     t.Minutes, t.Seconds)
            End Function
    
            Public Overrides Function ToString() As String
                Return String.Format("{0} {1} {2}", EmpName, Job.ToString, GetElapsed)
            End Function
    
        End Class
    
    
        Private col As Collection(Of TaskItem)
    
        Private myLV As ListView
    
        ' assign the LV when tasks are created
        Public Sub New(lvTask As ListView)
            myLV = lvTask
            col = New Collection(Of TaskItem)
        End Sub
    
        ' add new task with EmpName and JobCode
        Public Sub NewTask(sName As String, tj As TaskJobs)
    
            Dim ti As New TaskItem(sName, tj)
            col.Add(ti)
    
            ' LV layout: empname, job, elapsed, ID
            ' but only 3 columns so that ID is "hidden"
    
            Dim lvi As New ListViewItem(ti.EmpName)
            lvi.SubItems.Add(ti.Job.ToString)
            lvi.SubItems.Add(ti.GetElapsed)
            lvi.SubItems.Add(ti.ID)
    
            lvi.Group = myLV.Groups(LVGroups.Running.ToString)
            myLV.Items.Add(lvi)
    
        End Sub
    
        ' called from dbl click on a running task item
        Public Sub StopTask(lvi As ListViewItem)
    
            Dim ti As TaskItem = (From t In col Where t.ID = lvi.SubItems(3).Text).First
    
            ' the form doesnt check the status, so we must
            If ti.IsActive Then
                ti.EndTask()
                lvi.Group = myLV.Groups(LVGroups.Completed.ToString)
            End If
    
        End Sub
    
        ' called from the form timer tick event
        Public Sub UpdateDisplay()
            Dim ti As TaskItem
    
            ' iterate items to get ID of runners
            For Each lvi As ListViewItem In myLV.Groups(LVGroups.Running.ToString).Items
                ' ToDo add error checking
    
                ti = (From t In col Where t.ID = lvi.SubItems(3).Text).First
                lvi.SubItems(2).Text = ti.GetElapsed
    
            Next
    
        End Sub
    
        Public Function RunnersCount() As Integer
            Return GetActiveList.Count
        End Function
    
        Public Function GetCompletedList() As List(Of TaskItem)
            ' long form
            Dim tList As New List(Of TaskItem)
    
            For Each ti As TaskItem In col
                If ti.IsActive = False Then
                    tList.Add(ti)
                End If
            Next
    
            Return tList
    
            ' short form
            'Dim list = (From t In col Where t.IsActive = False).ToList
        End Function
    
    
        Public Function GetActiveList() As List(Of TaskItem)
            ' long form
            'Dim tList As New List(Of TaskItem)
    
            'For Each ti As TaskItem In col
            '    If ti.IsActive Then
            '        tList.Add(ti)
            '    End If
            'Next   
            'Return tList
    
            ' short form
            Dim list = (From t In col Where t.IsActive).ToList
            Return list
    
        End Function
    End Class
    

    用法:

    Public Class Form1
    
        Private myTasks As Tasks
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            myTasks = New Tasks(Me.lvTask)
            cboTask.Items.AddRange([Enum].GetNames(GetType(Tasks.TaskJobs)))
        End Sub
    

    添加任务:

    myTasks.NewTask(cboEmp.Text, CType(cboTask.SelectedIndex, Tasks.TaskJobs))
    

    停止任务:

    ' called from LV mousedoubleclick, so determine the item
    Dim lvi As ListViewItem = lvTask.GetItemAt(e.X, e.Y)
    myTasks.StopTask(lvi)
    

    显然,停止任务可能会自动将数据附加到导出文件中。该功能将在任务集合类中,它将在任务从集合中删除之前完成(可选 - 只要您可以区分活动与已完成,它们就不会伤害那里的任何东西)。

    定时器滴答事件:

        myTasks.UpdateDisplay()
    

    最后,打开Option Strict,尤其是因为人们将根据项目的输出做出决策。

    【讨论】:

    • 谢谢,我最终得到了这个工作。我正在使用 DataGridView 并循环遍历计时器的滴答事件上的行。效果很好,我希望我记得检查答案,因为您的解决方案非常好。感谢您的帮助!
    • 很高兴为您提供帮助 - 控制(LV 与 DGV)无关紧要,因为原理相同。当他们提供帮助时,接受/检查答案永远不会太晚。
    • 谢谢!现在全部工作并提交到共享点进行报告。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    相关资源
    最近更新 更多