2008-10-01 4 views
1

私はかなりよく構造化された.NET 3.5フォームアプリケーション(ユニットテスト、依存性注入、SoC、フォームは単に入力と出力をリレーし、ロジックは何もしません)と思っています。このビットをどのように動作させるかについてwinformsの知識があります。Windowsフォーム:ユーザーではなくアプリケーションによって開閉されるモーダルフォーム?

頻繁に発生するデータベースへの接続が失われた場合、これを検出して処理しています。接続が再確立されるまで、アプリケーションの使用をブロックするモーダルフォームがポップアップされます。私はユーザーの入力を待っているわけではなく、タイマーを使用してデータベースをポーリングしているので、これを行う方法は100%確信していません。私の試み

がその上にラベルでフォームを設計し、これを実行することでした:これは_dialog.Close()以降は動作しません

partial class MySustainedDialog : Form { 
    public MySustainedDialog(string msg) { 
     InitializeComponent(); 
     lbMessage.Text = msg; 
    } 
    public new void Show() { 
     base.ShowDialog(); 
    } 

    public new void Hide() { 
     this.Close(); 
    } 

} 

public class MyNoConnectionDialog : INoConnectionDialog { 
      private FakeSustainedDialog _dialog; 
    public void Show() { 
     var w = new BackgroundWorker(); 
     w.DoWork += delegate { 
      _dialog = new MySustainedDialog("Connection Lost"); 
      _dialog.Show(); 
     }; 
     w.RunWorkerAsync(); 
    } 

    public void Hide() { 
     _dialog.Close(); 
    } 
} 

クロススレッド呼び出しがあります。私はWindowsフォーム内でこの問題を解決する方法に関する情報を見つけることができましたが、フォーム自体を作成する必要があるこのような状況ではありません。

私がやろうとしていることを達成する方法を教えてもらえますか?

EDIT:私はUIのスレッドは、私は提案を完全に開いていますので、どのように働くかと途方もなく慣れていないだから注意してください、私は他のアイデアの不足のためにバックグラウンドワーカーを試してみました。また、現在作業しているフォームを閉じたくないことに気付く必要があります。これをその上に表示したいだけです。 OK/Cancelダイアログボックスと同様ですが、プログラムで開いて閉じることができます(そして、それはどのようなものかを制御する必要があります)

答えて

0

すべてのUIをメインのUIスレッドに保持する方が簡単ですBackgroundWorker?あなたのコードを見ずに言うのは難しいですが、私はあなたがそれを必要とするとは思わないのです。

タイマーを作成するときに、Timer.SynchronizingObjectを割り当ててメインUIスレッドを使用できるようにすることができます。そしてそれにこだわる?

申し訳ありませんが、あなたのプログラムの構造について詳しく知りませんでした。

+0

私は現在のフォームを閉じる必要はありませんが、その上にno connectionフォームが必要です。それ、どうやったら出来るの? –

+0

NoDatabaseFormフォーム=新規NoDatabaseForm(); form.ShowDialog(); アクティブなフォームの前に表示する必要があります。 –

+0

タイマーハンドラを実装する場合はいつでも、フォームにアクセスできる必要があります。そのため、データベースが戻ったときに再び閉じることができます。多分あなたの依存性注入などは混乱しているかもしれません。とにかくこれを行うことができる最小のアプリを書こうとすると、それをあなたのアプリに入れてください –

1

フォームの新しいインスタンスを実際に起動するためにバックグラウンドワーカーを使用する理由はありません。単純にUIスレッドから行うことができます。

+0

私は確信しています、どうすればいいですか? –

+0

単に、バックグラウンドワーカーの呼び出しを削除してから、デリゲートを使用するのではなく、コードにフォームを表示するだけです。 接続を試行して復元するプロセスは、別のプロセスに生成されるものです。 –

2

私はあなたの全体的なアプローチの正しさについてはよく分からないんだけど、特にあなたの質問は次のようにMySustainedDialog隠す()関数を変更してみてください答えるために:

public new void Hide() 
    { 
     if (this.InvokeRequired) 
     { 
      this.BeginInvoke((MethodInvoker)delegate { this.Hide(); }); 
      return; 
     } 

     this.Close(); 
    } 
+0

しかし、そのエラーを検索する際に推奨されるのと同じことが、MyNoConnectionDialogがフォームから継承しないため、InvokeまたはBeginInvokeがないことに注意してください。あなたはどうしますか? –

+0

MyNoConnectionDialog内のものではなく、MySustainedDialog内のものを変更します。 MyNoConnectionDialogはGUIコントロールに直接アクセスしないため、MyNoConnectionDialog内のものを変更する必要はありません。 – RickL

1

私が撮影した二つのアプローチがあります。同様の状況で。

1つは、メインのUIスレッドで完全に動作することです。メインのUIスレッドで起動するWindows.Forms.Timerインスタンスを使用してこれを行うことができます。

すべてのUIコンポーネントのシンプルさと完全なアクセスが可能です。欠点は、ブロッキングコールがユーザーエクスペリエンスに大きな影響を与え、ユーザーとのやりとりをまったく防ぐことです。そのため、最終的にUIアクションが発生するような長時間実行するコマンドが必要な場合(たとえば、データベースのチェックで数秒かかる場合など)、クロススレッドにする必要があります。

コードの観点から見れば最も簡単なクロススレッドソリューションは、BackgroundWorkerからControl.Invokeメソッドを呼び出すことです。

Invokeを使用すると、作業をコントロールに「ポスト」することができます。本質的に「plzはこれを実行するために所有スレッドを使用します」と言っています。

関連する問題