2011-07-14 6 views
3

したがって、私は最近、既存のWinFormsアプリケーションを引き継ぎました。システムトレイで実行するものに変更する必要がありますが、ユーザーが望むときにはフォームがポップアップします。問題ない。この質問によると:Mutex is being used to ensure only one copy of the app is running私のシステムトレイアプリでクロススレッドの問題を適切に処理するにはどうすればよいですか?

このアプリケーションには3つの主要コンポーネントがあります:カスタムアプリケーションコンテキスト(myContext)は、システムのすべての迷子を処理します。 myContextは、Gozer(myGozer)というクラスのインスタンスを作成します。 Gozerは本当のことをすべて行います。一定の時間間隔で一連の操作を実行します(ネットワークの状態を確認してから接続すれば、いくつかのことが実行されます)。それは、みんなが一連のイベントを通じて何が起こっているのかを知りましょう。 myFormが開かれると、myContextはmyGozerを渡します。

これは、私があらゆる種類のクロススレッディングの問題に突き当たるmyFormを開いたときです(何らかの方法でコントロールが使用されているときはいつでもmyListViewを操作します)。私が明らかにしていないことは、これに対処する最善の方法です。スレッドについてはほとんど知りません。私は30秒でスレッディングを理解することができる超大な脳を持っていません。そして、私は吸収するために食べることができる周りの誰も持っていない彼らのスレッドの優れた知識。

this questionによれば、私は単にsomeControl.InvokeRequiredをチェックして、デリゲートを介して問題のメソッドを呼び出します。これは機能します。しかし、今私は、私の頭の中で校正されていないいくつかの警鐘を発するコントロールを扱う必要があるたびに、たくさんのコードを削除するようになっています。私はまた、フォームからアプリケーションを終了するときに問題を発見しました。これにより、別のクロススレッディング例外がmyContextに戻されます。私は、アプリケーションをmyFormからもう終了させることが適切であるとは確信していませんが、この時点で他のクロススレッドの狂気が私を待っていますか?私は多くの副作用誘発性頭痛のために自分自身を設定しているように感じる。

私は実際に道路の潜在的な問題の束を作成することを心配していると思います。あるいは、Gozerの機能を拡張し、それがmyFormで動作する必要がある場合には、さらなる問題を作成するよう求められます。また、実行中にmyFormを開いたり閉じたりすると、クロススレッドに関する追加の問題が発生します。または、アプリケーションがすべてを爆発させる原因になります。

私には考慮すべき点がいくつかありますか?

注:これは.net 2.0アプリ用ですので、Jethroのソリューションはここでは機能しません。それはではないので、私はInvokeRequiredロジックを書く必要があるので、私はちょうどそれを行うつもりだと言った。私は次の年にこれを.net 3.5にアップグレードするつもりだと確信しています。下の提案されたクラスは、私が彼の問題をどのように処理するかです。私はそれを結果として答えとしてマークしています。

答えて

3

ここに使用できる拡張機能があります。私はそれを拾ったことを思い出すことはできません。

このように呼びます。

this.InvokeEx(p=> p.txtbox.Text = "Rad"); 


public static class ControlExtensions 
{ 
    public static TResult InvokeEx<TControl, TResult>(this TControl control, 
               Func<TControl, TResult> func) 
     where TControl : Control 
    { 
     return control.InvokeRequired 
       ? (TResult)control.Invoke(func, control) 
       : func(control); 
    } 

    public static void InvokeEx<TControl>(this TControl control, 
              Action<TControl> func) 
     where TControl : Control 
    { 
     control.InvokeEx(c => { func(c); return c; }); 
    } 

    public static void InvokeEx<TControl>(this TControl control, Action action) 
     where TControl : Control 
    { 
     control.InvokeEx(c => action()); 
    } 
} 
+0

これは、.NET 2.0のためです。面白そうに見えますが、Funcについて何をすべきか見てみましょう<> – peacedog

+0

うわー、私は最後のコメントを盗んだ。私が最初に書いたのは、 "2.0、私は拡張メソッドを使うことができませんでした"でしたが、4.0プロジェクトでこれを使って遊んでいたし、奇妙なパスをさまよって何かを混乱させました。しかし、ええ、私はこれを行うことはできません。私は本当に答えが好きです。 – peacedog

+0

拡張メソッドは、静的メソッドの単なる構文的な砂糖です。 2.0では動作を複製することはできますが、静的メソッドを手動で呼び出して最初のパラメータとしてコントロールを渡す必要があります。また、独自のバージョンのActionおよびFuncデリゲートを作成する必要があります(これらのデリゲートは3.0または3.5の一部です)。 –

4

アップグレードするときは、拡張方法を書いたくない場合は、別の方法があります。あなたはラムダ構文にも慣れていなければなりません。次に例を示します。

myTextBox.Invoke((Action) (() => myTextBox.Text = "text goes here")); 

私は呼び出しが必要な場合は、通常はチェックしないと、ちょうど(あなたはUIのスレッドとは異なるスレッドから更新している場合は、通常は知っている)呼び出しを行います。

注:私はこれまで同様の拡張方法を使用していましたが、私のすべてのプロジェクトで作成したり、すべてのプロジェクトに追加する必要があったライブラリで作成するのに疲れました。これはそれを行うための「シンプルな」1つの方法です。

ああ、あなたが複数の操作を行う必要がある場合にもとても似ているインラインを行うことができますが:

myListView.Invoke((Action) (() => 
    { 
     myListView.Columns.Add("Column 1", -2, HorizontalAlignment.Left); 
     myListView.Columns.Add("Column 2", -2, HorizontalAlignment.Left); 
     myListView.Columns.Add("Column 3", -2, HorizontalAlignment.Left); 
     myListView.Columns.Add("Column 4", -2, HorizontalAlignment.Center); 
    })); 
+0

私はちょうどInvokeRequiredのチェックが重要であると仮定しました。私は間違いなく別のスレッドからUIを更新しているので、私はそれをスキップすると思います。そのアプローチの欠点はありませんか?私はその代替の呼び出しのアプローチが好きです。 – peacedog

+0

コンセンサスのようです。このトピックに関する別のSOの質問がありました:http://stackoverflow.com/questions/5858557/invokerequired-doubt –

関連する問題