1

私はスタックオーバーフローを検索して、スレッドからUIスレッドにデータをマーシャリングする方法を探していましたが、3.5でそれを行うさまざまな方法を見つけました。

私にとってよりエレガントなソリューションの1つ。私はまだラムダとクロージャを学んでいますが、このソリューションはControl.Invokeと入力パラメーターです。

コードを完全には理解していませんが、使用方法は理解しており、問題を完全に解決することはできません。

invokeを呼び出して、文字列を別のメソッド(DisplayStatusUpdate(msg))に渡したいと思います。任意のポインタをいただければ幸いです。

    private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
    {
        DisplayStatusUpdate(e.LoggingEvent.RenderedMessage);
    }

    private void DisplayStatusUpdate(string text)
    {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
    }
4

2 に答える 2

5

これは、次のように、必要な数のパラメーターを使用して実行できます。

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
{
    DisplayStatusUpdate(e.LoggingEvent.RenderedMessage);
}

private delegate void DisplayStatusUpdateDelegate(string text);

private void DisplayStatusUpdate(string text)
{
     if(InvokeRequired)
         this.Invoke(new DisplayStatusUpdateDelegate(DisplayStatusUpdate), text);
     else
     {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
     }
}

私が現在のプロジェクトで使用している別の方法があり、コードを大幅に削減できます。詳細はこちら

このメソッドを実装する場合は、次のことを行う必要があります。

AOPファクトリを使用してフォームを作成します。

Form f = AOPFactory.Create<Form1>();
Application.Run(f);

次に、[RunInUIThread]属性を使用してイベントハンドラーを装飾します。Castleのメソッドインターセプトモデルを使用して、必要に応じて自動的に呼び出します。

したがって、上記のコードは次のようになります。

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
{
    _StatusTextBox.Text = _StatusTextBox.Text + text;
    _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
    _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
    _StatusTextBox.ScrollToCaret();
}

パフォーマンスに関しては、同等で少し遅いように見えますが、実行していることによっては問題ない場合もありますが、必要なコードは間違いなく少なくなります。

于 2009-08-23T21:44:56.333 に答える
2

C#3.5(またはそれ以降)を使用している場合は、キャプチャされた変数を使用できます。これにより、コードが簡略化される場合があります。

private void DisplayStatusUpdate(string text)
{
    this.Invoke(new MethodInvoker(() => 
    {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
    }));
}

ここでコンパイラが舞台裏で行うことは、テキストを保持するクラスを生成し、デリゲートを作成し、MethodInvokerそのデリゲートと生成されたクラスのインスタンスをInvokeメソッドに渡すことです。上記の設計では、もちろん、コードが同じスレッドですでに実行されている場合でも、デリゲートを作成してInvokeを呼び出すという不要な作業が行われます。しかし、このような方法は、パフォーマンスの問題になるほど頻繁に呼び出されるべきではないと思います。

Action必要に応じて、MethodInvokerの使用を、パラメーターのないデリゲート、またはを返す他のパラメーターのないデリゲートに置き換えることができますvoid

于 2009-08-23T21:54:41.133 に答える