2017-12-07 19 views
1

次のコードを2日間実行していましたが、昨日デバッグした後にSubが2回発射されたことがわかりました。いくつかの背景 - これは、すべてのパッケージを出荷する送料アプリケーションです。私は、メインフォームにリストビューを追加して、Easypostから返されるさまざまなレートを表示する必要があります。私が最初にリストビューを追加すると、アプリケーションはデバッグからうまく実行されましたが、コンパイル後に、リストビューが読み込まれた後に完全にハングしました。だから数日の検索の後、私は、リストビューが作成された後にアプリケーションGUIを続行できるようにするinvokeメソッドを追加しました。最初にレートが返されているかどうかを確認し、lvRates.InvokeRequiredにヒットしたときに呼び出しを実行し、EasyPostGetServicesを2回実行して2回目の返された2つ目のレートをロードするeasypostで出荷を作成します。ListViewの呼び出しはsubを2回実行します

Private Sub GetEasyPostServices() 


    EasyPostGetServices(dictEPFromAddress, dictEPToAddress, dictEPPackage) 

    If EasyPostShipment.rates.Count > 0 Then 
     If lvRates.InvokeRequired Then 
      lvRates.Invoke(New MethodInvoker(AddressOf GetEasyPostServices)) 
     Else 
      For Each rate As Rate In EasyPostShipment.rates 
       lvRates.Items.Add(New ListViewItem({rate.carrier, rate.rate, UCase(rate.service), rate.id})) 
      Next 
     End If 

    Else 
     MsgBox("Based on your inputs or preferences, no shipping services were available. Shipping services shown ignore your preferences. If none are shown, there are no shipping services available for this order.") 
    End If 
End Sub 

私の質問は、なぜコードが2回実行されているのか、それがどうして起こらないのかです。私は呼び出しを移動したが、他のすべてのものは、exeから実行するとGUIがフリーズすることを試みる。

+0

あなた自身で答えることができます:ブレークポイントを設定し、コールスタックを調べます。あなたはDataSourceで作業することができ、B)あなたは幅*などを* numbers * – Plutonix

+0

「GlobalVariables」として保存できるので、DataGridViewがより良い選択となるようです。それはコードのにおいです。 – LarsTech

+0

あなたはサブ呼び出し自体を伝えているので、2回呼び出されることは意味がありますか? invokeが必要な場合、GetEasyPostServicesは別のスレッド上の別のコピーを呼び出します。したがって、2つの実行が行われます。 2回目の実行は、呼び出しを必要としないスレッドで実行されているため、elseブロックにドロップされて終了します。 – soohoonigan

答えて

1

これは元の質問に基づいています。ボタンのクリックにBackgroundWorkerを追加して、GetEasyPostServicesをUI以外のスレッドで実行するようにしました。ここでの要点は、UI呼び出しを適切に呼び出す方法です。下の3つの方法はそれを実証しています。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    ' this method is running on the UI thread as it handles a UI event 
    Dim bw As New System.ComponentModel.BackgroundWorker() 
    AddHandler bw.DoWork, New System.ComponentModel.DoWorkEventHandler(Sub(oo, ee) GetEasyPostServices()) 
    ' this call causes GetEasyPostServices to run on a non-UI thread 
    bw.RunWorkerAsync() 
End Sub 

Private Sub GetEasyPostServices() 
    ' running on a non-UI thread. Any UI calls must be invoked 
    Cursor.Current = Cursors.WaitCursor 
    Try 
     Dim frAddress As New Dictionary(Of String, Object)() From { 
      {"street1", "12345 Hill Dr"}, 
      {"street2", ""}, 
      {"city", "sometown"}} 

     Dim toAddress As New Dictionary(Of String, Object)() From { 
      {"street1", sAdd1}, 
      {"city", sCity}, 
      {"state", sRegion}, 
      {"verifications", New List(Of String)() From {"delivery"}}} 

     Dim package As New Dictionary(Of String, Object) 
     If GlobalVariables.giLength > 0 Then 
      package.Add("length", GlobalVariables.giLength.ToString) 
      package.Add("width", GlobalVariables.giWidth.ToString) 
      package.Add("height", GlobalVariables.giHeight.ToString) 
      package.Add("weight", (sLbs * 16) + sOz) 
     End If 

     EasyPostGetServices(frAddress, toAddress, package) 

     If EasyPostShipment.rates.Count > 0 Then 
      ' hide the UI invocation logic in methods 
      updateListView() 
     Else 
      MsgBox("Based on your inputs or preferences, no shipping services were available. Shipping services shown ignore your preferences. If none are shown, there are no shipping services available for this order.") 
      clearAndFocusTbOrder() 
     End If 
    Finally 
     Cursor.Current = Cursors.Default 
    End Try 
End Sub 

' these methods manage their own UI invocation. 

Private Sub updateListView() 
    If lvRates.InvokeRequired Then 
     lvRates.Invoke(New Action(AddressOf updateListView)) 
    Else 
     lvRates.Visible = True 
     lvRates.Items.Clear() 
     For Each rate As Rate In EasyPostShipment.rates 
      lvRates.Items.Add(New ListViewItem({rate.carrier, rate.rate, UCase(rate.service), rate.id})) 
     Next 
     SortListView() 
     lvRates.Items(0).Selected = True 
     Button1.Visible = True 
    End If 
End Sub 

Private Sub SortListView() 
    If lvRates.InvokeRequired Then 
     lvRates.Invoke(New Action(AddressOf SortListView)) 
    Else 
     lvRates.Sort() 
    End If 
End Sub 

Private Sub clearAndFocusTbOrder() 
    If tbOrderID.InvokeRequired Then 
     tbOrderID.Invoke(New Action(AddressOf clearAndFocusTbOrder)) 
    Else 
     tbOrderID.Clear() 
     tbOrderID.Focus() 
    End If 
End Sub 

これは、何を、どこで、なぜ呼び出すのかということです。あなたの例では、GetEasyPostServicesがUIで起動されたかどうかは不明でした。そうしないとUI呼び出しを正しく呼び出す方法を示すことができませんでした。 UIスレッドが現在UIスレッドにないので、UI呼び出しを呼び出す必要があります。それが「理由」です。

また、不要な処理やUIスレッドのハングアップを防ぐために、UIスレッドで最小限のコードを実行することが重要です。元の設定ですべてのコードが1回実行された後、すべてのUIスレッドで実行されました。

+0

ありがとうlarstech。 djvでドロップし、完全に働いた。このマルチスレッディングは余分な作業をたくさん追加します。みんなありがとう – DTAp

関連する問題