2017-10-05 9 views
0

私はAS400からSQLへのいくつかのクエリ呼び出しを行うメソッドを呼び出すアプリケーションを持っています。 long story short私はスレッドを開始し、このスレッドをこのスレッドに入れました。ボタンの残りの部分は応答しません。このループが完了している間、私はアプリケーションが応答可能である必要があります。たとえば、ユーザーがアプリケーションを閉じる必要がある場合、私は開いているスレッドをシャットダウンしてアプリケーションを閉じる必要があります。どのように私はこれを正しく行うだろうか?私はUIの機能の別のスレッドを作ることについていくつかを読んだが、それは働かない。どのように私はこれを設定するのですか?別のを呼び出すために、その関数の使用を呼び出しまたはBeginInvokeメソッド内の任意の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スレッド上で再び同じコードを実行します最初は今度は同じ長い実行コードを2回実行しています。 – 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を更新する関数です。 InvokeとBeginInvokeはUIスレッドで強制的に呼び出しを行います。

あなたが最後にタスクを待つ必要がある場合は、単に使用:

Dim t = Task.Factory.StartNew(Sub() 
            SomeFunctionYouWantToCallInTheBackground() 
           End Sub) 
:あなたのバックグラウンドタスクは、戻り値はありません

Dim result = t.Result 

場合は、代わりにこのような関数のサブを使用することができます

結果がないので、t.Wait()を使用して終了します。詳細については

、Googleの「System.Threading.Tasks.Task」

関連する問題