0

現在、シリアル通信からデータを読み取るアプリケーションがあります。アプリケーション全体を通して、このデータを UI に表示する必要があるため、BeginInvoke を使用してテキスト ボックス/ラベル/数値/進行状況バーを更新するメソッドを作成しました。

しかし、これは面倒になり始めています。すべてのコントロールが独自の「Setter」を必要とするため、すでに 20 ほどのメソッドがあり、それらはすべて基本的に同じことを行います。

これを特定のコントロールに一般化する簡単な方法 (例: ラベル用に 1 つ、テキスト ボックス用に 1 つだけ) はわかりますが、UI のデータを更新するために呼び出すことができるメソッド (おそらく拡張) を 1 つだけ持つのが理想的です。 .

これが、いたるところに散らばっている元の方法です。

private void SetCell1Cell2Async(decimal value)
    {
        if (spinCell1Cell2.InvokeRequired)
        {
            spinCell1Cell2.BeginInvoke(new EventHandler(delegate
            {
                spinCell1Cell2.Value = value;
            }));
        }
        else
        {
            if (spinCell1Cell2.IsDisposed) return; // Do not process if the control has been disposed of
            if (spinCell1Cell2.IsHandleCreated)
            {
                // This handle may not be created when creating this form AFTER data is already flowing
                // We could capture this data for future display (i.e. via deferUpdate = true or similar), but it is easier to ignore it
                // i.e. Do Nothing
                return;
            }
            spinCell1Cell2.Value = value;
        }
    }

Text現在の方法は次のとおりです (これは、プロパティを使用してデータを表示するコントロールで機能します)。

delegate void SetTextAsyncCallback(Control ctrl, string text);
public static void SetTextAsync(this Control invoker, string text)
{
    if (invoker.InvokeRequired)
    {
        invoker.BeginInvoke(new SetTextAsyncCallback(SetTextAsync), invoker, text);
    }
    else
    {
        if (invoker.IsDisposed) return; // Do not process if the control has been disposed of
        if (!invoker.IsHandleCreated)
        {
            // This handle may not be created when creating this form AFTER data is already flowing
            // We could capture this data for future display (i.e. via deferUpdate = true or similar), but it is easier to ignore it
            // i.e. Do Nothing
            return;
        } 
        invoker.Text = text;
    }
}

ご覧のとおり、このメソッドは、Textプロパティを使用してそのデータを表示するすべてのもので機能します。

string理想的には、更新するプロパティを「渡す」ことができ、doubledecimal、などを取るメソッドを提供できるようにしたいのbooleanですが、ここからどこへ行くべきか少し迷っています。

どんな助けでも感謝します。

4

1 に答える 1

2

フォームに次のようなものを使用して、より普遍的なソリューションを作成します。

delegate void ActionCallback();

private void SetText()
{
    this.SafeInvoke(() =>
        {
            if (spinCell1Cell2.IsDisposed) return;
            if (!spinCell1Cell2.IsHandleCreated) return;
            // Do stuff
        });
}

private void SafeInvoke(ActionCallback action)
{
    if (this.InvokeRequired)
        this.Invoke(action);
    else
        action();
}

デリゲートを使用すると、実際のアクションを 1 回宣言するだけでよく、実行のタイプは後で (SafeInvoke メソッドで) 決定されます。いくつかの拡張メソッドが必要な場合は、次の例をご覧ください。

public delegate void ActionCallback();

public static void SafeInvoke(this Form form, ActionCallback action)
{
    if (form.InvokeRequired)
        form.Invoke(action);
    else
        action();
}

public static void SafeSetText(this Control ctl)
{
    var form = ctl.FindForm();
    if (form == null) return; // or do something else

    form.SafeInvoke(() =>
        {
            // Do stuff
        });
}

編集 あなたの質問をもう一度読んだ後、これは実際にはあなたが尋ねたものではないことに気付いたので、より適切な例を挙げます:

public static void SafeUpdate<T>(this T ctl, ActionCallback action) where T : Control
{
    var form = ctl.FindForm();
    if (form == null) return; // or do something else

    SafeInvoke(action);
}

// Then in some other method
{
    textBox1.SafeUpdate(() =>
    {
        textBox1.Text = "123";
        textBox1.ForeColor = Color.Red;
    });
}
于 2012-10-03T09:35:04.103 に答える