1

私は代表者があまり得意ではなく、内部で何が起こっているのかわかりません。cross thread operation別のスレッドからUIアイテムにアクセスするとエラーが発生します。

私がやりたいのは、Utilityクラスにジェネリック関数を記述して、任意のメソッド/コードブロックを関数に渡すことができるようにすることです。私はそれを次のような多くの方法で行うことができます:

  1. delegate void UpdateGui(Control c, Action action);
    public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired)
            {
                UpdateGui updaterdelegate = new UpdateGui(Do);
                c.TopLevelControl.Invoke(updaterdelegate, new object[] { c, action });
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    
  2. public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke((Action)delegate { Do(c, action); });
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    
  3. public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired)
            {
                c.TopLevelControl.Invoke(action);
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    
  4. public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke(new MethodInvoker(() => action()));
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    
  5. public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke(new MethodInvoker(delegate { action(); }));
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    
  6. public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke((MethodInvoker)delegate { action(); });
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    

アプローチ1と2は基本的に同じであり、4、5、6も同じだと思います。私の質問は次のとおりです。

  1. アプローチ(1&2)、3、(4、5&6)の違いは何ですか?つまり、一方が処理/処理し、他方が処理しない場合はどうなるでしょうか。

  2. cross thread operationエラーを回避する適切な方法は、すべての状況を処理するという意味で、できれば簡潔で読みやすいという意味で何ですか?

4

1 に答える 1

3

上記の「3番目の」アプローチ(を使用するだけAction)は、より単純で効率的です。を使用する他のアプローチdelegateでは、別のメソッド(delegateキーワードを介した匿名メソッド)を作成します。このメソッドは、元のデリゲート(パラメーター)を呼び出しますactionが、これは不要です。

3番目のオプションは、渡されたものを直接使用しますAction。これはより単純です。

最初のオプションも同様ですが、その場合は、不要な値(Control)を渡し、さらにカスタムデリゲートを定義する必要があります(Action<Control,Action>代わりに使用できます)。コントロールが使用されていないため、この複雑さを追加する理由はありません。

ちなみに、例外ハンドラー内で再スローする場合は、スタックトレースを適切に保持するため、throw;(ではなく)を使用することをお勧めします。throw ex;

catch (Exception ex)
{
    // Do whatever, ie: logging
    throw;
}

ログに記録せず、単に再スローする予定の場合は、try/をcatch完全に省略できます。

于 2012-10-15T18:45:09.493 に答える