2016-11-24 8 views
-1

現在、VB.NETのconsoleApplicationで一連のライブラリ呼び出しを自動化しています。ファンクションコールは、通常、ユーザが選択した一連の入力を必要とします。私の問題は、これらの関数のセットが、プログラムでアクセスできないDialogBoxインスタンスを作成し、それらが相互作用するまでプログラムの実行を一時停止することです。DialogBoxの実行を一時停止するMultiThreadedソリューション

今、私は以下のコードに従って複数のスレッドを使用してこの問題を解決しようとしました。

Public Sub StartFormFunction(ByVal inputValue As String) 
     frameWork.showHiddenDialogBox(inputValue) 
End Sub 

Public Sub threadFunction(ByValue inputValue As String) 
    Dim nrOfOpenForms As Integer = Application.OpenForms.Count()  
    Try    
     Dim t As New Thread(New ParameterizedThreadStart(AddressOf StartFormFunction)) 
     t.Priority = Threading.ThreadPriority.Highest 
     t.Start(inputValue) 
     'Wait until the prompt has been created.    
     While (Application.OpenForms.Count() = nrOfOpenForms) And (t.IsAlive) 
     End While   
     if Not t.IsAlive Then 
      log.Error("Thread did not open dialogBox") 
      Return 
     End If 
     'Select preffered button on dialogBox 
     Dim isFinished As Boolean = False 
     For Each curForm As Form In Application.OpenForms 
      For Each btn As Button In curForm.Controls.OfType(Of Button) 
       If btn.Name = "Button3" Then 
        btn.PerformClick() 
        isFinished = True 
       Exit For 
      End If 
      Next 
      if isFinished Then 
       Exit For 
      End If 
     Next 
     'Wait until thread completed Function 
     While t.IsAlive 
     End While 

     Catch ex As Exception   
      log.Error("Thread Error") 
     End Try 
End Sub 

コンソールアプリケーションでControl.Invoke()を使用する方法がまだ見つかりませんでした。その理由は、これが使用されていないためです。 コードを完全に実行できるようにする方法は、回避しようとしているCheckForIllegalCrossThreadCallsを無効にすることです。

複数のスレッドを使用せずにダイアログボックスにアクセスするという問題を解決することは可能ですか?そうでない場合は、サブコールを呼び出すことで問題を解決できますか?

編集 詳細な情報が記載されていない場合があります。 私の問題は、私のアプリケーションが、コードから範囲外に保たれるクラス内の命令のセットを実行するメソッドshowHiddenDialogBox()を実行することです。このアクセスできないクラスは、すべての機能が実行されたときにフォームを表示します。このフォームが表示されると、ユーザーが入力を促すまで、アプリケーションはコードのすべての実行を一時停止します。 これを回避するには、複数のスレッドを使用する必要があります。ただし、この新しいスレッドは、すべてのコンテンツが表示されている間にこのフォームを所有します。これは、ボタンには、他のスレッドにアクセスする必要があることが含まれています。

+0

内のすべてのコントロールのために、このサブ。 'frameWork.showHiddenDialogBox(inputValue)'とは何ですか?あなたはいつ呼び出す必要がありますか?呼び出しが必要なマルチスレッドコードはありません。 - フォームを開くが、実行をブロックしないようにしたいので、Form.Show()の代わりに 'Form.ShowDialog()'を呼び出す可能性が高い。 –

+0

詳細が不明なことをお詫び申し上げます。 ShowHiddenDialogBoxは、私にとってはアクセスできないクラスに対する一連の変更をコミットするメソッドです。このメソッドは操作を実行し、ボタンがクリックされるまでコードの実行を中断するメッセージボックスを最後に表示します。これは、スコープの外に存在し、アクセス不可能なフォームインスタンスです。私の今の目標は、フォームを閉じてフォームを閉じてスレッドを解放するときに、別のスレッドが入力をコミットしているときにフォームが表示されたときに「ロック」できるスレッドでこのメソッドを実行することです。 – Han123

+0

それは扱うのが難しい問題です。あなたがしなければならないことは、 'For Each btn'ループ全体を呼び出すことです。タイラーのコードを使用しますが、現在のフォームのみを呼び出し、複数行の 'Sub()'であなたのものを行います。 –

答えて

0

はいけないこれだけのコードでコントロールを呼び出し、「CheckForIllegalCrossThreadCalls」を使用します。

'Insert this in a module 
<Runtime.CompilerServices.Extension()> 
Public Sub InvokeCustom(ByVal Control As Control, ByVal Action As Action) 
    If Control.InvokeRequired Then Control.Invoke(New MethodInvoker(Sub() Action()), Nothing) Else Action.Invoke() 
End Sub 

コールあなたの質問は、情報が欠けているスレッド

textbox1.InvokeCustom(sub() textbox1.text = "abc") 
+0

@VisualVincent 'Control.Invoke(Action)'がすでにサブの中にあることがわかります。それはとにかくチェックが呼び出されることです。複数のコントロールの場合、あなたは正しいですが、PanelまたはTableLayoutを含むフォームに問題がありました。速度については...彼が持っているコントロールの数に依存しますが、同時に10を超えるコースパがフォームを呼び出す方が良いですが、2または3の場合はなぜ完全なフォームを呼び出すのですか? – Tyler

+0

(私のコメントはそれほど厳しくはないと書き直しました) 'ControlInvoke(Action)'を呼ぶだけで、アクションを呼び出すための 'MethodInvoker'デリゲートとラムダ式のメソッドをなぜ作りたいのですか?また、複数のUI要素を同時に更新している場合は、各Invokeが実行に少し時間がかかるため、すべてのコントロールを呼び出す代わりに、 'Form.InvokeCustom'を呼び出して複数のラムダを使用する方がよいでしょう。 –

+0

'が2または3であればなぜ完全なフォームを呼び出すのですか?' - 'Control.Invoke()'メソッドは親フォームを探して、それを起動します。唯一の時間差は、UIスレッドキュー(すべてのコントロールとフォームが実行される)にメッセージを入れるだけなので、絶対親を見つけるのにかかる時間です。 –

関連する問題