2009-11-08 22 views
5

SQL Serverの型付きデータセットに標準の.Netデータバインディングを使用して、単純なデータUIを作成しています。UI以外のスレッドでモーダルダイアログを実行

すべてのDataAdapterでFillを呼び出して、別のユーザーがデータを変更した場合にデータベースから新しいデータを取得するリロードボタンがあります。

これは、UIがフリーズするまでに時間がかかります。 UIスレッドで実行する必要があります。または、データバインディングイベントハンドラはスレッド間例外をスローします。

私は、UIスレッドがデータベースに接続している間、バックグラウンドスレッド(これはアニメーション化できるように)でモーダルの「お待ちください」ダイアログを表示したいと思います。

UI以外のスレッドでモーダルダイアログボックスを表示するにはどうすればよいですか?


EDIT:私は、ベストプラクティスは、バックグラウンドでの動作を実行することであることを認識してんだけど、私が行うことができないため、データバインディングのイベントのこと。

答えて

8

逆の操作を行う必要があります。長時間実行しているプロセスをバックグラウンドスレッドで実行し、UIスレッドをユーザーの操作に応答できるようにしておきます。

処理中にユーザーアクションをブロックする場合は、モーダルダイアログを含む多くのオプションがあります。バックグラウンドスレッドが処理を完了したら、結果

+0

私が質問で説明したように、私はできません。私はこれがベストプラクティスであることをよく承知しています。 – SLaks

+0

あなたはまだできると思います。これは、バックグラウンドスレッドがデータを直接更新してはならないことを意味します。それらを取得し、それらをパッケージ化し、メインスレッドに委譲してUIを更新します – mfeingold

+0

あなたのジレンマを理解していますが、私はまだ考えているものが代替品よりも良い(問題が少ない)と考えています – mfeingold

0
using(var frmDialog = new MyPleasWaitDialog()) { 
    // data loading is started after the form is shown 
    frmDialog.Load += (_sender, _e) { 
     // load data in separate thread 
     ThreadPool.QueueWorkItem((_state)=> { 
      myAdapter.Fill(myDataSet); 
      // refresh UI components in correct (UI) thread 
      frmDialog.Invoke((Action)myDataControl.Refresh); 
      // close dialog 
      frmDialog.Invoke((Action)frmDialog.Close()); 
     } 
    } 

    // shows dialog 
    frmDialog.ShowDialog(this); 
} 
+0

DataGridにバインドされていない別のDataSetにデータをロードし、DataGridを新しいデータセットに再バインドする必要があります。 および/またはデータセット/データテーブルで "BeginLoadData()"および "EndLoadData"を使用してみてください。 – TcKs

+1

私がこの質問で説明しようとしたように、 'myAdapter.Fill'は、バックグラウンドスレッドで呼び出されたときにグリッドのデータバインディングイベントハンドラにInvalidOperationExceptionをスローします。テーブル上で 'BeginLoadData'を呼び出すことは役に立ちません。 – SLaks

+1

したがって、別のデータセットを入力してから、データグリッドを「新しい」(塗り潰された)データセットインスタンスに再バインドする必要があります。 – TcKs

2

イベントは、おそらくデータ転送オブジェクトのいくつかの種類を使用して、UIから分離する必要があるデータバインディングで実行されるコードについてメインスレッドに知らせることができます。

その後、別のスレッドまたはBackgroundWorkerでクエリ操作を実行し、UIスレッドをそのままにしておくことができます。

編集:この問題を解決するために本当に簡単な方法は、InvokeRequired.Invokeを使用して、独自のデリゲートで実行するイベントを取得することです。それはメソッドのUIコンテキストを提供します。私の同僚はスタイルが外に出ているようにこれを行います。この方法で行うのはめったに良いことではないので、私は終わりまで気にしません...しかし、高速なソリューションが必要な場合は、これが機能します。 (私は職場にいないので、私と一緒にサンプルを持っていないので、何かを考え出すつもりです)

編集2:あなたが求めているものが可能かどうかわかりません。私は、別のスレッドでモーダルダイアログを作成したサンプルアプリケーションを作成し、それはモードレスになりました。モーダルダイアログを使用する代わりに、他のコントロールやコントロールのセットを使用して、進行状況の変更を示すことができますか?ここで

+0

これを行う簡単な方法はありますか?また、更新イベントで標準のデータバインディングを使用しますか?このプロジェクトをすばやく完了しようとしています。 – SLaks

+0

Re。編集:私は 'Invoke'呼び出しをDataGridの中に入れることはできません。 – SLaks

+0

Re:Edit 2:あなたは非常に正しいかもしれません。簡単な質問だったら、ここでそれを聞いたことはありません。フォームにコントロールを置くことは、それはさらに悪いことです。異なるスレッドが所有するフォーム上にいくつかのコントロールを持つことは不可能です。 – SLaks

0

が...「読み込んでレコード」または類似のを示すために、データの読み込みを行うためのBackgroundWorkerを使用して、ユーザーフレンドリーなフォームを実行する例である

public void Run() 
    { 
     bgWorkrFillDS = new BackgroundWorker(); 
     bgWorkrFillDS.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkrFillDS_RunWorkerCompleted); 
     bgWorkrFillDS.DoWork += new DoWorkEventHandler(bgWorkrFillDS_DoWork); 
     bgWorkrFillDS.RunWorkerAsync(); 
    } 

    void bgWorkrFillDS_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker bgWrkrFillDS = (BackgroundWorker)sender as BackgroundWorker; 
     if (bgWrkrFillDS != null) 
     { 
      // Load up the form that shows a 'Loading....' 
      // Here we fill in the DS 
      // someDataSetAdapter.Fill(myDataSet); 
     } 
    } 


    void bgWorkrFillDS_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // Hide or unload the form when the work is done 
    } 

・ホープ、このことができます... は注意してください、 Tom。

+1

質問をお読みください。バックグラウンドスレッドで 'someDataSetAdapter.Fill'を呼び出すと、InvalidOperationExceptionがスローされます。 – SLaks

0

新しいデータセットを作成し、バックグラウンドで読み込み、UIスレッドでDataSet.Mergeを呼び出してこの問題を解決しました。アドバイスをいただき、ありがとうございました。追加ボーナスとして

、これは(唯一のオープンなしグリッドで働いていた背景、中Fillを呼び出す)するために使用されるよりもはるか速く実行されます。なぜ誰が知っていますか?

関連する問題