4

私たちのチームは、古いものに代わる新しい採用ワークフロー システムを作成しています。私は、古いデータを新しいスキーマに移行する任務を負っています。スキーマが根本的に異なり、単純な TSQL スクリプトは適切なソリューションではないため、小規模な Windows フォーム プロジェクトを作成することでこれを行うことにしました。

作業を行うメインのシール クラス 'ImportController' は、次のデリゲート イベントを宣言します。

public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e);
public static event ImportProgressEventHandler importProgressEvent;

メイン ウィンドウは、新しいスレッドを使用してそのクラスの静的メソッドを開始します。

Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData));
dataProcessingThread.Name = "Data Importer: Data Processing Thread";
dataProcessingThread.Start(settings);

ImportProgressEvent 引数は、文字列メッセージ、進行状況バーの最大 int 値、および現在の進行状況 int 値を運びます。Windows フォームはイベントにサブスクライブします。

ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent);

独自のデリゲートを使用して、この方法でイベントに応答します。

    private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax);

private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e)
            {
                this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax);
            }

最後に、プログレス バーとリストボックスが更新されます。

private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax)
        {
            string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string item in items)
            {
                this.lstTasks.Items.Add(item);
            }

            if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax)
            {
                this.ImportProgressBar.Maximum = progressMax;
                this.ImportProgressBar.Value = currentProgress;
            }
        }

問題は、ListBox が非常に迅速に更新されるように見えることですが、とにかくバッチがほぼ完了するまでプログレス バーは移動しませんか ??? 何が得られますか?

4

6 に答える 6

2

たぶん、BackgroundWorkerコンポーネントを試すことができます。糸脱毛が容易になります。ここでの例:

于 2008-08-15T09:38:36.613 に答える
0

Application.DoEvents();範囲外かもしれませんが、ステータスバーダイアログのキャンセルボタンを押すなど、GUIパーツをユーザー入力に反応させるために実行すると便利な場合があります。

于 2008-08-15T09:58:15.797 に答える
0

万が一WindowsVistaを実行していますか?いくつかの仕事関連のアプリケーションでまったく同じことに気づきました。どういうわけか、プログレスバーが「アニメート」するときに遅延があるようです。

于 2008-08-15T10:01:57.550 に答える
0

@ジョン

リンクをありがとう。

@意思

スレッドプーリングは1つのスレッドしか生成しないことを私は知っているので、スレッドプーリングによるメリットはありません。スレッドの使用は、SQL Serverが読み取りと書き込みで処理されている間、純粋にレスポンシブUIを使用することです。それは確かに短命のスレッドではありません。

スレッジハンマーに関しては、あなたは正しいです。しかし、結局のところ、私の問題はスクリーンと椅子の間にありました。他のバッチよりもはるかに多くの外部キーレコードを含む異常なデータのバッチがあるようですが、プロセスの早い段階で選択されたため、currentProgressが10秒間++されません。

@全て

あなたのすべての入力に感謝します、それは私がコードの他の場所を見るように私を考えさせました、そしてそれは私が再びエラーが通常人間であることを証明する謙虚さの私のahaa瞬間につながりました:)

于 2008-08-15T10:07:06.447 に答える
-1

このすべてのプロセスの間、UIスレッドが自由に実行されていることを確認しますか?つまり、参加やその他の待機でブロックされた状態ではありませんか?それは私にはそれがどのように見えるかです。

BackgroundWorkerを使用するという提案は、良い提案です。Refresh/ Update呼び出しの負荷で問題を解決するために、スレッジハンマーを使用するよりも間違いなく優れています。

また、BackgroundWorkerはプールスレッドを使用します。これは、独自の短命のスレッドを作成するよりも操作しやすい方法です。

于 2008-08-15T09:50:34.517 に答える
-1

スレッドプーリングは1つのスレッドしか生成しないことを私は知っているので、スレッドプーリングによるメリットはありません。スレッドの使用は、SQL Serverが読み取りと書き込みで処理されている間、純粋にレスポンシブUIを使用することです。それは確かに短命のスレッドではありません。

OK、ありがとうございます。バグを見つけてよかったですが、BackgroundWorkerを見たことがありますか?それはあなたがしていることをほぼ正確に行いますが、標準化された方法で(つまり、独自のデリゲートなしで)、新しいスレッドを作成する必要はありません-どちらも(おそらく小さいですが、それでも役立つ)利点です。

于 2008-08-15T10:20:01.663 に答える