シナリオがあります。(Windows フォーム、C#、.NET)
- ユーザー コントロールをホストするメイン フォームがあります。
- ユーザーコントロールは、メソッドを直接呼び出すと、
UserControl_Load
ロードメソッドの実行中にUIが応答しなくなるなど、重いデータ操作を行います。 - これを克服するために、別のスレッドにデータをロードします(既存のコードをできるだけ変更しようとしています)
- データをロードするバックグラウンド ワーカー スレッドを使用しました。完了すると、作業が完了したことをアプリケーションに通知します。
- 今、本当の問題が来ました。すべての UI (メイン フォームとその子ユーザー コントロール) は、プライマリ メイン スレッドで作成されました。ユーザーコントロールのLOADメソッドでは、ユーザーコントロールのコントロール(テキストボックスなど)の値に基づいてデータをフェッチしています。
擬似コードは次のようになります。
コード 1
UserContrl1_LoadDataMethod()
{
if (textbox1.text == "MyName") // This gives exception
{
//Load data corresponding to "MyName".
//Populate a globale variable List<string> which will be binded to grid at some later stage.
}
}
それが与えた例外は
クロススレッド操作が無効です: コントロールが作成されたスレッド以外のスレッドからアクセスされました。
これについてもっと知るために、グーグルで調べたところ、次のコードを使用するような提案が出てきました
コード 2
UserContrl1_LoadDataMethod()
{
if (InvokeRequired) // Line #1
{
this.Invoke(new MethodInvoker(UserContrl1_LoadDataMethod));
return;
}
if (textbox1.text == "MyName") // Now it wont give an exception
{
//Load data correspondin to "MyName"
//Populate a globale variable List<string> which will be binded to grid at some later stage
}
}
BUT BUT BUT... 振り出しに戻ったようです。アプリケーションが再び応答しなくなります。1行目のif条件の実行によるものと思われます。ロード タスクは、私が生成した 3 番目のスレッドではなく、親スレッドによって再度実行されます。
この認識が正しかったのか間違っていたのか、私にはわかりません。私はスレッド化が初めてです。
これを解決するにはどうすればよいですか? また、Line#1 if ブロックの実行の影響は何ですか?
状況は次のとおりです。コントロールの値に基づいてグローバル変数にデータをロードしたいと考えています。子スレッドからコントロールの値を変更したくありません。私は子スレッドからそれを行うつもりはありません。
したがって、対応するデータをデータベースから取得できるように、値にのみアクセスします。