1

私のdllでは、次のようなイベントを公開しています。

 public delegate void LogMsgEventHandler(object sender, LogEventArgs e);

        public event LogMsgEventHandler newLogMessage;

        public class LogEventArgs : EventArgs
        {
            public string logMsg;
        }

        protected virtual void OnChanged(LogEventArgs e)
        {
            if (newLogMessage != null)
                newLogMessage(this, e); 
        }

さまざまなメソッドがイベントを発生させて、操作の詳細をログに記録します。dllを使用するメインフォームで、ログメッセージをリストボックスに出力します。

 slotUtil.newLogMessage += new slotUtils.LogMsgEventHandler(slotUtil_newLogMessage);

..

  void slotUtil_newLogMessage(object sender, slotUtils.LogEventArgs e)
        {
            lbDebug.Items.Add(e.logMsg);
        }

問題は、ロギングイベントの発生が速すぎると、フォームがフリーズすることです。これは糸脱毛の問題だと思いますか?フォームが流動的に更新されるこのデザインを修正するにはどうすればよいですか?これは悪いデザインですか?私の代替デザインIDは、すべてのログをdllのプライベート文字列に格納し、特定のメソッドが呼び出されたときにのみログをダンプするというものでした。考え?

ありがとう!

4

1 に答える 1

2

dllのクラスのインスタンスが別のスレッドにない場合は、スレッドの問題ではありません。イベントハンドラー

void slotUtil_newLogMessage(object sender, slotUtils.LogEventArgs e)
        {
            lbDebug.Items.Add(e.logMsg);
        }

登録されているのと同じスレッドで実行されます。

したがって、インスタンスがUIスレッドにある場合、このイベントハンドラーはUIスレッドでも実行されます。新しいリストボックスの再描画をトリガーする新しいアイテムをリストボックスに追加します。イベントが描画よりも速く発生している場合、イベントハンドラーはキューに積み上げられ、Invalidatesが終了するのを待ちます。これが当てはまる場合は、少なくとも次のようなことを行う必要があります。

System.Windows.Forms.Timer t;
public Form1()
{
    InitializeComponent();

    t = new System.Windows.Forms.Timer();
    t.Interval = 1000;
    t.Tick += new EventHandler(t_Tick);
}

void t_Tick(object sender, EventArgs e)
{
    for(int i = 0;i<count;i++)//you must add here only those valid strings, can't use foreach
        lbDebug.Items.Add(item);
    count = 0;
}

static int count = 0;
static string[] items = new string[5];
void slotUtil_newLogMessage(object sender, slotUtils.LogEventArgs e)
{
            t.Stop();
            items[count++] = e.logMsg;
            if (count >= items.Length)
            {
                foreach (string item in items)
                    lbDebug.Items.Add(item);
                count = 0;
            }
            else
            {
                t.Start();
            }
 }

リストボックスへの項目の追加は、5つのログの準備ができたとき、または最後のログから1秒が経過したときに行われます。リストボックスに追加する前に、配列にログをいくつでも追加できます(サイズを変更するだけです)。

于 2012-11-17T12:40:09.160 に答える