シナリオがあります。(Windowsフォーム、C#、. NET)
- いくつかのユーザーコントロールをホストするメインフォームがあります。
- ユーザーコントロールが重いデータ操作を行うため、
UserControl_Load
メソッドを直接呼び出すと、ロードメソッドの実行中にUIが応答しなくなります。 - これを克服するために、別のスレッドでデータをロードします(できる限り既存のコードを変更しないようにします)。
- 私は、データをロードするバックグラウンドワーカースレッドを使用しました。完了すると、アプリケーションに作業が完了したことを通知します。
- 今、本当の問題が起こりました。すべてのUI(メインフォームとその子ユーザーコントロール)は、プライマリメインスレッドで作成されました。usercontrolのLOADメソッドでは、userControlのコントロール(テキストボックスなど)の値に基づいてデータをフェッチしています。
擬似コードは次のようになります。
コード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 ...正直に戻ってきたようです。アプリケーションは再び応答しなくなります。if条件の1行目が実行されたことが原因と思われます。ロードタスクは、親スレッドによって再度実行され、私が生成した3番目のタスクではありません。
私がこれを正しいと思ったのか、間違っていたのかわかりません。私はスレッディングが初めてです。
これをどのように解決しますか?また、Line#1 ifブロックの実行の効果は何ですか?
状況は次のとおりです。コントロールの値に基づいて、データをグローバル変数にロードします。子スレッドからコントロールの値を変更したくありません。子スレッドからこれを行うつもりはありません。
したがって、値にアクセスするだけで、対応するデータをデータベースからフェッチできます。