使用工作线程和ui线程

时间:2017-10-05 21:05:16

标签: vb.net multithreading

我有一个应用程序调用一个方法,通过SQL对AS400进行一些查询调用。长话短说我启动了一个线程并将此方法放入此线程中。但其余按钮没有响应我需要应用程序在此循环完成时响应。例如,如果用户需要关闭应用程序,我需要关闭打开的线程并关闭应用程序。我该怎么做呢?我读了一些关于创建另一个UI功能的线程,但它不起作用。我该如何设置?

Imports Microsoft.VisualBasic
Imports System.Threading

Public Class frmAbsenceTracking

Public Sub ScheduledToday()
    Dim yr, wk, dy, i As Integer

    Dim dbconn As New WES.Core.Database.SQLConnection
    Dim Empdbconn As New WES.Core.Database.SQLConnection
    Dim sql, empSQL As String
    Dim ds As DataSet
    Dim empds As DataSet


    dbconn("@DTDDWD") = DateAdd("d", -1, Now).Day
    dbconn("@DTMMWD") = DateAdd("d", -1, Now).Month
    dbconn("@DTCCWD") = ((DateAdd("d", -1, Now).Year).ToString).Substring(0, 2)
    dbconn("@DTYYWD") = ((DateAdd("d", -1, Now).Year).ToString).Substring(2)

    sql = "SELECT yearwd, wk#wd, day#wd From ISERIES.WES.WQDATA.PRWKDAPF WHERE DTDDWD = @DTDDWD AND DTMMWD = @DTMMWD AND DTYYWD = @DTYYWD AND DTCCWD = @DTCCWD"
    ds = dbconn.FillDataSet(sql)

    yr = ds.Tables(0).Rows(0)("yearwd")
    wk = ds.Tables(0).Rows(0)("wk#wd")
    dy = ds.Tables(0).Rows(0)("day#wd")

    Empdbconn("@year") = yr
    Empdbconn("@week") = wk
    Empdbconn("@day") = dy

    empSQL = "SELECT emp#sd FROM ISERIES.WES.WQDATA.PRSDTll9 WHERE yearsd = @year and wk#sd = @week and day#sd = @day"
    empds = Empdbconn.FillDataSet(empSQL)

    Dim Employee(empds.Tables(0).Rows.Count) As Integer

    If Label2.InvokeRequired Then
        Label2.BeginInvoke(New ScheduledTodayDelegate(AddressOf ScheduledToday))
    Else
        Label2.Text = "Last Scan Started: " + Now
        Label2.Refresh()
    End If

    Dim Absentees(empds.Tables(0).Rows.Count) As Integer
    'may throw out of bounds for i
    For i = 0 To empds.Tables(0).Rows.Count - 1
        Employee(i) = CInt(empds.Tables(0).Rows(i)("emp#sd"))

        If EmpList.InvokeRequired Then
            EmpList.BeginInvoke(New ScheduledTodayDelegate(AddressOf ScheduledToday))
        Else
            EmpList.Items.Add("Scannning Employee:" + Employee(i).ToString)
            EmpList.Refresh()
        End If

        If hasAbsences((Employee(i)), yr, wk, dy) = True Then
            Absentees(i) = Employee(i)
            ' BuildReport(Absentees(i))
        End If
    Next




    Label1.Text = "Last Completed Scan: " + Now
    If EmpList.Items.Count > 10000 Then
        EmpList.Items.Clear()
    End If
End Sub
Public Sub BuildReport(Employee As Integer)

End Sub

Private Delegate Sub ScheduledTodayDelegate()
Private Delegate Function exitAppDelegate()
Public Function hasAbsences(empNumber As Integer, yr As Integer, wk As Integer, dy As Integer) As Boolean
    Dim dbconn As New WES.Core.Database.SQLConnection
    Dim dbconn2 As New WES.Core.Database.SQLConnection
    Dim sql, sql2 As String
    Dim ds, ds2 As DataSet
    Dim Parts = Split(Now.ToShortDateString, "/")
    dbconn("@Employee") = empNumber
    dbconn("@year") = yr
    dbconn("@week") = wk
    dbconn("@day") = dy


    ' Dim ReturnDataStuff = returnDateStuff(yr, wk, dy)
    '  Dim Assemble = AssembleDate(CInt(Parts(2).Substring(0, 2)), CInt(Parts(2).Substring(2)), CInt(Parts(0)), CInt(Parts(1)))
    sql = "SELECT yearsd, wk#sd, day#sd FROM ISERIES.WES.WQDATA.PRSDTll7 WHERE (emp#sd = @Employee AND yearsd < @year) OR (emp#sd = @Employee AND yearsd = @year AND wk#sd < @week) OR (emp#sd = @Employee AND yearsd = @year AND wk#sd = @week AND day#sd < @day) ORDER BY yearsd asc, wk#sd asc, day#sd asc"
    ds = dbconn.FillDataSet(sql)

    dbconn2("@Employee") = empNumber
    dbconn2("@StartDate") = returnDateStuff(ds.Tables(0).Rows(ds.Tables(0).Rows.Count - 2)("yearsd"), ds.Tables(0).Rows(ds.Tables(0).Rows.Count - 2)("wk#sd"), ds.Tables(0).Rows(ds.Tables(0).Rows.Count - 2)("day#sd"))
    dbconn2("endDate") = AssembleDate(CInt(Parts(2).Substring(0, 2)), CInt(Parts(2).Substring(2)), CInt(Parts(0)), CInt(Parts(1)))

    sql2 = "SELECT * FROM ISERIES.WES.WQDATA.PRWKPNl7 WHERE emp#wp = @Employee and pdatwp > @StartDate AND pdatwp < @endDate"


    ds2 = dbconn2.FillDataSet(sql2)

    If ds2.Tables(0).Rows.Count <= 0 Then
        If EmpList.InvokeRequired Then
            EmpList.BeginInvoke(New ScheduledTodayDelegate(AddressOf ScheduledToday))
        Else
            EmpList.Items.Add(empNumber.ToString + "out for 2 or more days")
            EmpList.Refresh()
        End If

        Return True
        Else
            Return False
    End If

End Function

Public Function returnDateStuff(yr As Integer, wk As Integer, dy As Integer) As Long
    Dim ccx, yyx, mmx, ddx As Integer
    Dim ds As DataSet
    Dim sql As String
    Dim dbconn As New WES.Core.Database.SQLConnection
    dbconn("@year") = yr
    dbconn("@week") = wk
    dbconn("@day") = dy

    sql = "SELECT DTDDWD, DTMMWD, DTYYWD, DTCCWD FROM ISERIES.WES.WQDATA.PRWKDAPF WHERE yearwd = @year AND wk#wd = @week AND day#wd = @day"
    ds = dbconn.FillDataSet(sql)
    ddx = ds.Tables(0).Rows(0)("DTDDWD")
    mmx = ds.Tables(0).Rows(0)("DTMMWD")
    yyx = ds.Tables(0).Rows(0)("DTYYWD")
    ccx = ds.Tables(0).Rows(0)("DTCCWD")

    Return AssembleDate(ccx, yyx, mmx, ddx)

End Function

Public Function AssembleDate(cc As Integer, yy As Integer, mm As Integer, dd As Integer) As Long
    Dim t, tc, ty, tm, td As String

    tc = CStr(cc)
    ty = CStr(yy)
    tm = CStr(mm)
    td = CStr(dd)

    If Len(ty) = 1 Then
        ty = "0" & ty
    End If

    If Len(tm) = 1 Then
        tm = "0" & tm
    End If

    If Len(td) = 1 Then
        td = "0" & td
    End If

    t = tc + ty + tm + td

    Return CLng(t)

End Function
Private Sub exitApp()
    If ExitBtn.InvokeRequired Then
        ExitBtn.BeginInvoke(New ScheduledTodayDelegate(AddressOf exitApp))
    Else
        Application.Exit()
    End If

End Sub
Private Sub ForceBtn_Click(sender As Object, e As EventArgs) Handles ForceBtn.Click
    Dim t1 As System.Threading.Thread = New System.Threading.Thread(AddressOf Me.ScheduledToday)
    t1.Start()
    'ScheduledToday()
End Sub

Private Sub ExitBtn_Click(sender As Object, e As EventArgs) Handles ExitBtn.Click
    Dim t2 As System.Threading.Thread = New System.Threading.Thread(AddressOf Me.exitApp)
    t2.Start()
End Sub
End Class

1 个答案:

答案 0 :(得分:0)

你可以使用像这样的任务......

Imports System.Threading.Tasks

...

Dim t = Task.Factory.StartNew(Function() 
                                 Return SomeFunctionYouWantToCallInTheBackground()
                              End Function)

要在该函数内执行任何UI更新,请使用Invoke或BeginInvoke调用另一个将更新UI的函数。 Invoke和BeginInvoke强制调用在UI线程中发生。

如果您需要等待任务结束,请使用:

Dim result = t.Result

如果你的后台任务没有返回值,你可以使用Sub而不是像这样的函数:

Dim t = Task.Factory.StartNew(Sub() 
                                  SomeFunctionYouWantToCallInTheBackground()
                              End Sub)

并使用t.Wait()等待它完成,因为没有结果。

有关详情,请访问Google“System.Threading.Tasks.Task”