0

タスクとデリゲートで奇妙な問題が発生します。問題のコードは、dotNET 4.5.1、VS2013 で実行されています。フォームのコードには、グリッドを更新するサブがあり、呼び出しが必要かどうかを確認し、必要な場合はデリゲートを呼び出します。同じモジュールで呼び出されたタスクが実行されると、期待どおりに機能し、問題はありません。スレッド化されているかどうかに関係なく、グリッドは適切に更新されます。

ただし、同じものが別のモジュールから呼び出された場合、デリゲートは呼び出されず、ビジュアル コンポーネントは更新されません。明確にするために、少し骨抜きにされた擬似コード..

フォームのモジュールで:

Private Delegate Sub DoWhateverDelegate(ByVal _____)
Public Sub DoWhatever(ByVal _____)
    If MyComponent.InvokeReqired
        Dim Delegated As New DoWhateverDelegate(AddressOf DoWhatever)
        Debug.Print("The delegate fired")
        Invoke(Delegated, _____)
    Else
        ' .. carry on as usual ..
    End If
End Sub

他の場所....

Task.Run(Sub()
             ' .. various things I'd rather not block the UI thread with ..
             DoWhatever()
         End Sub)

正常に動作します。DoWhatever を呼び出す Task.Run_ _を実行できます。ただし、別のモジュールでタスクを作成して DoWhatever を呼び出すと、デリゲートが起動されず、そのビジュアル コンポーネントが更新されません。コードは同じで、同じモジュールでは機能しますが、別のモジュールでは機能しません。

私はおそらく露骨に明らかな何かを見逃しています..誰かが私の間違いを指摘してくれますか? ありがとう。

編集 - 明確にするために、他のモジュールは単なるコードであり、ソリューション全体でフォームは 1 つだけです。プログラムの起動時に自動的に作成され、他のフォーム作成は行われません。

4

1 に答える 1

1

スレッド固有の問題である必要があります。これをチェックして:

Public Class Form1

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    foo.DoSomething()

End Sub
End Class

デリゲートを持つクラス:

Public Class foo

Public Shared Sub DoSomething()
    Task.Run(Sub() UpdateText())
End Sub

Public Delegate Sub UpdateTextDelegate()
Public Shared Sub UpdateText()

    Dim f = Form1
    'Dim f As Form1 = Application.OpenForms("Form1")

    If f.InvokeRequired Then
        Dim d As UpdateTextDelegate = AddressOf UpdateText
        f.Invoke(d)
    Else
        f.TextBox1.Text = "Hi"
    End If

End Sub

End Class

コードを実行すると、テキスト ボックスは更新されません。2 番目f=....(OpenForms から参照を取得するもの) を使用すると、更新されます。にアクセスしようとしてdefault instance、UI スレッドの外にいる場合は、フォームの新しいインスタンスが作成されます。つまり、コンテンツは更新されますが、そのフォームは表示されないため、表示されません。

: を使用して問題を解決することはお勧めしませOpenForms。フォームを正しくインスタンス化することをお勧めします!

コードに新しいモジュール/クラスを追加します。

Module Startup

Public MyForm1 As Form1

Public Sub main()

    MyForm1 = New Form1
    Application.Run(MyForm1)

End Sub

End Module

プロジェクトのプロパティ -> アプリケーションに移動します。アプリケーション フレームワークを無効Sub Mainにし、開始オブジェクトとして選択します。MyForm1アプリで、または任意の名前を付けてフォームにアクセスします。それで問題はなくなるはずです。

于 2013-11-01T13:54:08.310 に答える