Проследяване на изминалото време за набор от задачи

Опитвам се да напиша малко 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

person tom_bea    schedule 09.10.2014    source източник


Отговори (1)


Възприех по-ориентиран подход, който може да е по-икономичен, що се отнася до таймерите, но има много прост интерфейс. Ядрото е 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
comment
Благодаря, в крайна сметка наистина успях. Използвах DataGridView и преминавах през редовете на събитието за отметка на моя таймер. Работи перфектно, иска ми се да бях запомнил да проверя отговорите, тъй като вашето решение е много добро. Благодаря за вашата помощ! - person tom_bea; 17.10.2014
comment
радвам се да помогна - управлението (LV срещу DGV) няма значение, тъй като принципът е същият. и никога не е късно да приемете/проверите отговор, когато те помогнат. - person Ňɏssa Pøngjǣrdenlarp; 17.10.2014
comment
Благодаря! Всичко работи сега и се изпраща на sharepoint за докладване. - person tom_bea; 17.10.2014