vb.net线程子程序比调用子程序

时间:2018-08-28 10:53:55

标签: vb.net multithreading performance

我知道此问题已经发布,但从未真正回答过,或者我听不懂答案:)

我的问题是,当我在线程中调用此Sub时,执行代码大约需要4秒钟,但是如果我创建一个简单的Call Sub(如在代码中注释过),则大约需要450毫秒。

我有一个包含2个Subs的简单程序:

  1. 在主表单上报告进度

  2. 执行一些“ For”循环

    Imports System.Data.SqlClient
    
    Public Class Form1
    Public Delegate Sub ProzentDelegate(ByVal Prozent As Double)
    
    Dim G_I_Temp As Integer = 0
    Dim G_S_Prüfziffer As String
    Dim G_S_Präfix As String
    Dim G_I_Zähler As Integer
    Dim G_I_Stellen As Integer
    Dim G_D_Step As Integer = 1
    Dim G_I_Position As Integer
    Dim DT_G_Prüftabelle As DataTable
    Dim DR_G_Prüftabelle As DataRow
    Dim thisLock As New Object
    Dim conn As String = "Data Source=SR-SQLWVS;Initial Catalog=Barcode;Integrated Security=True"
    Dim sourceconn As New SqlConnection(conn)
    Dim adap As SqlDataAdapter
    Dim cmd As SqlCommand = New SqlCommand("SELECT TOP(10) * FROM dbo.Prüf_Tabelle", sourceconn)
    
    Dim Thrd_preview As Threading.Thread
    
    
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
        sourceconn.Open()
    
        cmd.Connection = sourceconn
    End Sub
    
    Public Sub ReportProgress(ByVal Prozent As Double)
        ProgressBar1.Value = Prozent
    End Sub
    
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If RB_Thread.Checked Then
    
            If Thrd_preview IsNot Nothing Then Thrd_preview = Nothing
            Thrd_preview = New Threading.Thread(AddressOf DoSomeWork)
            Thrd_preview.IsBackground = True
            Thrd_preview.Start()
    
        Else
            DoSomeWork()
        End If
    End Sub
    
    Private Sub DoSomeWork()
    
    
        Dim ds As New DataSet
        DT_G_Prüftabelle = ds.Tables.Add("Prüf_Tabelle")
    
        Dim L_I_Counter, L_I_Counter2 As Integer
        Dim L_I_Ende As Integer
        Dim L_I_Step As Integer
        Dim L_I_Nutzen As Integer = 1
        L_I_Step = 1
        L_I_Ende = Val(TB_Auftrag_neu_Anzahl.Text)
        G_I_Stellen = 8
        G_S_Prüfziffer = "1"
        G_S_Präfix = "00"
        If TB_Info_Increment.Text = "" Then TB_Info_Increment.Text = 1
    
    
    
    
    adap = New SqlDataAdapter("SELECT TOP(10) * FROM dbo.Prüf_Tabelle", sourceconn)
    
        adap.FillSchema(DT_G_Prüftabelle, SchemaType.Mapped)
    
        DT_G_Prüftabelle.Rows.Clear()
    
        Dim pre As Date = Now
    
        For L_I_Counter = 1 To (L_I_Ende * L_I_Step) Step L_I_Step
            For L_I_Counter2 = 1 To L_I_Nutzen
                DR_G_Prüftabelle = DT_G_Prüftabelle.NewRow
                DR_G_Prüftabelle.Item("Auftrag_Lfd_nr") = TB_KeyLot.Text
                DR_G_Prüftabelle.Item("Position") = G_I_Position
                G_I_Position += G_D_Step
                DR_G_Prüftabelle.Item("Barcode_soll") = F_Berechnung((Trim(Str(Val(TB_Auftrag_neu_Von.Text) + L_I_Counter - 1))).PadLeft(G_I_Stellen, "0"))
                DT_G_Prüftabelle.Rows.Add(DR_G_Prüftabelle)
    
            If ProgressBar1.InvokeRequired Then
                ProgressBar1.BeginInvoke(New ProzentDelegate(AddressOf ReportProgress), (L_I_Counter * 100) / (L_I_Ende * L_I_Step))
            Else
                ReportProgress((L_I_Counter * 100) / (L_I_Ende * L_I_Step))
            End If
    
            Next
    
    
    
        Next
    
    
        MsgBox(Now.Subtract(pre).TotalMilliseconds.ToString & " ms.")
    
    
    End Sub
    
    
    Function F_Berechnung(ByVal L_Nummer As String) As String
        Dim L_B_Gerade As Boolean = False
        Dim L_I_Prüfziffer As Integer
        Dim L_I_Stellen As Integer
        Me.G_I_Temp = 0
    
    Select Case G_S_Prüfziffer
        Case "0"
            F_Berechnung = L_Nummer
        Case "1"
            F_Berechnung = G_S_Präfix & Trim(L_Nummer)
        Case "2"
            F_Berechnung = G_S_Präfix & Trim(L_Nummer)
        Case "3"
            F_Berechnung = L_Nummer
            '
        Case "5"    '-----Mod 10 gewichtung 31...-----
            L_Nummer = G_S_Präfix & Trim(L_Nummer)
            L_I_Stellen = Len(L_Nummer)
            For Me.G_I_Zähler = L_I_Stellen To 1 Step -1
                Me.G_I_Temp += Val(Mid(L_Nummer, Me.G_I_Zähler, 1)) * IIf(L_B_Gerade, 1, 3)
                L_B_Gerade = Not L_B_Gerade
            Next
            L_I_Prüfziffer = IIf(10 - Me.G_I_Temp Mod 10 = 10, 0, 10 - Me.G_I_Temp Mod 10)
            F_Berechnung = Trim(L_Nummer) & Trim(Str(L_I_Prüfziffer))
            '
        Case "6"    '-----Mod 10 gewichtung 13...-----
            L_Nummer = G_S_Präfix & Trim(L_Nummer)
            L_I_Stellen = Len(L_Nummer)
            For Me.G_I_Zähler = L_I_Stellen To 1 Step -1
                Me.G_I_Temp += Val(Mid(L_Nummer, Me.G_I_Zähler, 1)) * IIf(L_B_Gerade, 3, 1)
                L_B_Gerade = Not L_B_Gerade
            Next
            L_I_Prüfziffer = IIf(10 - Me.G_I_Temp Mod 10 = 10, 0, 10 - Me.G_I_Temp Mod 10)
            F_Berechnung = Trim(L_Nummer) & Trim(Str(L_I_Prüfziffer))
            '
    
    
        Case Else
            F_Berechnung = L_Nummer
    
    End Select
    
    End Function
    

我尝试进行进度报告,但是结果是相同的。

希望您对我有一些建议或解决方案。我会非常感激。

2 个答案:

答案 0 :(得分:1)

尝试这些更改

更改此

        If ProgressBar1.InvokeRequired Then
            ProgressBar1.Invoke(New ProzentDelegate(AddressOf ReportProgress), Progr)
        Else
            ReportProgress(Progr)
        End If

            ReportProgress(Progr)

并将方法ReportProgress更改为

Public Sub ReportProgress(ByVal Prozent As Double)
    Me.BeginInvoke(Sub()
                       ProgressBar1.Value = Prozent
                   End Sub)
End Sub

看看那有什么不同。不需要检查InvokeRequired,答案始终是。

答案 1 :(得分:0)

只想报告我找到了解决方案。

主要问题是以下代码行:

DR_G_Prüftabelle.Item("Auftrag_Lfd_nr") = TB_KeyLot.Text

因此,如果我从另一个线程而不是从主线程开始此Sub,则对于每个单个循环,它都必须进入主线程并从TextBox中获取Paramater,然后再回到Thread至Loop中。

我把它取出来,在一开始就声明了一个变量,并为其分配了TextBox值,它的工作方式就像魅力。

我还从dbasnett那里得到了一个建议,即在没有If-Else的情况下每次都调用Invoke Reporting。

你们提供了很多帮助。谢谢你!