0

私のアプリケーションでは、リストボックスにファイルを追加したいと思います。ファイルがpcap拡張子でない場合は、ファイルパスをクラスに送信し、それをpcap拡張子に変換してから、このファイルをリストボックスに追加します。アプリケーションがこのファイルの追加または変換を完了するまでGUIが応答しないnamyファイルを追加することを選択した場合、スレッドを介してこれをすべて行うオプションを追加する方法を知りたいと思います。

private void btnAddfiles_Click(object sender, EventArgs e)
{
    System.IO.Stream stream;
    OpenFileDialog thisDialog = new OpenFileDialog();
    thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
    thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
        "|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
    thisDialog.FilterIndex = 1;
    thisDialog.RestoreDirectory = false;
    thisDialog.Multiselect = true;
    thisDialog.Title = "Please Select Source File";

    if (thisDialog.ShowDialog() == DialogResult.OK)
    {
        if (thisDialog.FileNames.Length > 0)
        {
            lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
        }

        foreach (String file in thisDialog.FileNames)
        {
            try
            {
                if ((stream = thisDialog.OpenFile()) != null)
                {
                    using (stream)
                    {
                        string fileToAdd = string.Empty;
                        Editcap editcap = new Editcap();


                            BackgroundWorker backgroundWorker = new BackgroundWorker();
                            backgroundWorker.WorkerReportsProgress = true;
                            backgroundWorker.DoWork += new DoWorkEventHandler(
                            (s3, e3) =>
                            {
                                if (!editcap.isLibpcapFormat(file))
                                {
                                    fileToAdd = editcap.getNewFileName(file);
                                }
                                else
                                {
                                    listBoxFiles.Items.Add(file);
                                }
                            });

                            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
                                (s3, e3) =>
                                {
                                    listBoxFiles.Items.Add(fileToAdd);
                                });

                            backgroundWorker.RunWorkerAsync();

                        lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
                    }
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
            }
        }

    }
}
4

2 に答える 2

2

UIスレッドで多くの作業を行っているため、アプリケーションがフリーズしています。長時間実行されるタスクをバックグラウンドスレッドに移動してから、UIスレッドでUIを更新する必要があります。

それを行うために最初に行う必要があるのは、UI操作から長時間実行するタスクを分離することです。現在、この2つを混ぜ合わせているため、にマップする方法について混乱が生じていますBackgroundWorker

リストボックスを繰り返し更新する必要がなく、最後にすべてのアイテムを一度に追加するだけで問題ない限り(これは、リストボックスに期待することです)、ファイルIOを1つで実行できます。配置し、結果をある種のコレクションに追加し(Listここではおそらく適切です)、次に、リスト内のすべてのアイテムをに追加できますListBox(またはデータバインディングを使用できます)。

その変更を行うと、aのようなものを使用するように移行するのBackgroundWorkerは非常に簡単です。にデータを入力し、バックグラウンドで実行してから、を設定するListIO作業。次に、イベントはそのリストを取得し、アイテムをに追加します。DoWorkResultRunWorkerCompletedListBox

リストボックスにアイテムを追加する必要がある場合は、時間の経過とともに1つのアイテム、次のアイテムなどが表示されます。次に、それを「進捗状況のレポート」と見なし、構築された関連する進捗状況レポート機能を使用します。にBackgroundWorker。ループ内の進行状況を更新し、進行状況レポートのイベントハンドラーで、指定された値を取得して、に配置しますListBox

実装は次のとおりです。

private void btnAddfiles_Click(object sender, EventArgs e)
{
    System.IO.Stream stream;
    OpenFileDialog thisDialog = new OpenFileDialog();
    thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
    thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
        "|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
    thisDialog.FilterIndex = 1;
    thisDialog.RestoreDirectory = false;
    thisDialog.Multiselect = true;
    thisDialog.Title = "Please Select Source File";

    if (thisDialog.ShowDialog() == DialogResult.OK)
    {
        if (thisDialog.FileNames.Length > 0)
        {
            lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
        }

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.DoWork +=
        (s3, e3) =>
        {
            //TODO consider moving everything inside of the `DoWork` handler to another method
            //it's a bit long for an anonymous method
            foreach (String file in thisDialog.FileNames)
            {
                try
                {
                    if ((stream = thisDialog.OpenFile()) != null)
                    {
                        using (stream)
                        {
                            Editcap editcap = new Editcap();
                            if (!editcap.isLibpcapFormat(file))
                            {
                                string fileToAdd = editcap.getNewFileName(file);
                                backgroundWorker.ReportProgress(0, fileToAdd);
                            }
                            else
                            {
                                backgroundWorker.ReportProgress(0, file);
                            }


                            lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
                        }
                    }
                }

                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        };

        backgroundWorker.ProgressChanged +=
            (s3, arguments) =>
            {
                listBoxFiles.Items.Add(arguments.UserState);
            };

        backgroundWorker.RunWorkerAsync();

    }
}
于 2012-12-12T20:27:06.473 に答える
0

あなたはBackgroundWorkerでそれを行うことができます:ツールボックスを介してフォームにbackgroundWorkerを追加します。

それを開始します:

backgroundWorker.RunWorkerAsync(new string[] {parm1, parm2});

backgroundWorkerにイベントを追加します([プロパティ]ウィンドウ)

DoWorkを使用して計算を行います。次に、RunWorkerCompletedを使用して設定を適用します。

于 2012-12-12T20:27:47.377 に答える