Я выбрал более ООП-подход, который может быть более экономичным с точки зрения таймеров, но имеет очень простой интерфейс. Ядром является TaskItem, который отслеживает задание и время, а затем класс коллекции, чтобы их выставлять, запускать и останавливать. Спрятав как можно больше функций на как можно более низком уровне, все становится проще.
Я использовал только один таймер и не понимаю, зачем вам нужно несколько таймеров для одной задачи. Если TaskItem записывает DateTime
при запуске (это происходит автоматически, когда он создается в моем), то вам вообще не нужны никакие таймеры. Прошедшее время всегда рассчитывается с использованием StartedTime
и либо DateTime.Now
(для текущей задачи), либо CompletedTime
для завершенных задач. Я не вижу, где таймер что-то добавляет.
Вам придется сделать много модов для ваших целей. Это не сохраняет завершенные элементы и не удаляет их из списка, но может дать вам отправную точку. Это также вещь первого прохода; тут и там наверняка есть проблемы.
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
, тем более что люди будут принимать решения на основе результатов проекта.
person
Ňɏssa Pøngjǣrdenlarp
schedule
10.10.2014