2017-10-05 207 views
0

我有一個應用程序調用通過SQL對AS400執行一些查詢調用的方法。長話短說我開始了一個線程,並把這個方法放到這個線程中。但其餘的按鈕沒有響應,我需要應用程序響應,而這個循環完成。例如,如果用戶需要關閉應用程序,則需要關閉打開的線程並關閉應用程序。我將如何正確地做到這一點?我讀了一些關於製作UI功能的另一個線索,但它不起作用。我如何設置?使用工作線程和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 
+2

你的一些「InvokeRequired」代碼只是再次運行相同的代碼UI線程,其中有你試圖避免長時間運行的查詢上首先。現在你正在運行相同的長時間運行代碼......兩次。 – LarsTech

+0

像@LarsTech說,你只是在UI線程上重新運行你的'ScheduledToday()'方法。調用的目的是僅調用實際**更新UI線程**的部分。查看我的答案以獲取示例和指導(向下滾動到_ **訪問UI線程**):https://stackoverflow.com/a/45571728/3740093 –

回答

0

你可以使用這樣的任務...

Imports System.Threading.Tasks 

....

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

要做到這一點功能使用內部的任何UI更新調用或BeginInvoke調用另一個函數將會更新用戶界面。 Invoke和BeginInvoke強制調用在UI線程中發生。

如果需要等待任務結束,只需使用:

Dim result = t.Result 

如果你的後臺任務沒有返回值,你可以用它代替這樣的功能一子:

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

並使用t.Wait()等待它完成,因爲不會有Result。

欲瞭解更多信息,谷歌「System.Threading.Tasks.Task」