-2

私は、ファイルからアクティブに読み取り、そのファイル内の情報をリアルタイムで分析して UI に表示するアプリケーションを開発しています。

私が読んだことはすべて、これを行うにはある種のスレッドを使用する必要があることを示しています。私はバックグラウンド ワーカーを調査し、実行時に別のスレッドを作成して、そのスレッドを使用してすべての UI 要素を更新しようとしました。

元のUI要素が別のスレッドで作成されたため、クロススレッド呼び出しを行うことができない(または行うべきではない)ときに問題が発生します。

それらを更新するスレッドでこれらの UI 要素を作成する方法はありますか? これを行う最善の方法は何ですか?

編集: この投稿 (現在は削除されています) への返信があり、これを行う方法を説明しています。説明した方法でコードを更新した後、これは私が使用した更新されたコードです。ファイル システム ウォッチャーを追加するまでは、すべて問題ありません。追加するとすぐに、クロススレッド呼び出しを行わないという同じエラーが発生します。

セッションは、ログ ファイルを解析する私が作成したクラスです。

private Session s1 = new Session("");
private FileSystemWatcher fsw;
private OpenFileDialog ofd1 = new OpenFileDialog();

private BackgroundWorker bgw;

private bool logActive = false;

public frmMain()
{
    InitializeComponent();
    bgw = new BackgroundWorker();
    bgw.WorkerReportsProgress = true;
    bgw.ProgressChanged += HandleProgressChanged;
    bgw.DoWork += HandleDoWork;

    fsw = new FileSystemWatcher(@"H:\Logs", "*.txt");
    fsw.SynchronizingObject = this;
    fsw.IncludeSubdirectories = false;
    fsw.EnableRaisingEvents = true;
    fsw.NotifyFilter = NotifyFilters.Size;
    fsw.Changed += new FileSystemEventHandler(fsw_OnChanged);
}

private void frmMain_Load(object sender, EventArgs e)
{
    ofd1.Filter = "log files (*.txt)|*.txt|All files (*.*)|*.*";
    ofd1.FilterIndex = 2;
    ofd1.RestoreDirectory = true;
}

private void fsw_OnChanged(object source, System.IO.FileSystemEventArgs e)
{
    bgw.RunWorkerAsync();
}

// this runs on the UI thread
// here's where you update the UI based on the information from the event args
private void HandleProgressChanged(object sender, ProgressChangedEventArgs e)
{
    for (int i = s1.previousLineNumber; i < s1.GetMessageCount(); i++)
    {
        ListViewItem lvi = new ListViewItem((s1.GetMessage(i).date).ToString());
        lvi.SubItems.Add(s1.GetMessage(i).type.ToString());
        lvi.SubItems.Add(s1.GetMessage(i).data);
        listView1.Items.Add(lvi);
    }
}

// this runs on a background thread; you cannot modify UI controls here
private void HandleDoWork(object sender, DoWorkEventArgs e)
{
    s1.ParseLiveFile();
    bgw.ReportProgress(100);
}
4

1 に答える 1

0

UI を更新するには、Invoke または BeginInvoke を使用する必要があります。

void LengthyProcessInThread()
{
   ...
   foreach(var item in file)
   {
       Invoke(delegate() {
          .. Update UI here.
       });
   }
}

Invoke はコントロールのメソッドです。UI を含むフォーム。

あなたの探求の幸運を祈ります。

于 2013-03-03T21:12:51.133 に答える