0

私のアプリケーションでは、基本的に大きなディスプレイ (カスタム ユーザー コントロール) で構成される新しい Windows フォーム (Monitor と呼ばれます) があり、それ自体はグリッドに配置された多くの小さなグラフ (ユーザー コントロールも含む) で構成されています。モニター フォームをインスタンス化すると、新しい表示オブジェクトが作成され、続いて多数のチャート コントロールが作成されます。次に、チャート コントロールが「ディスプレイ」のコントロール コレクションに追加され ( Controls.Add(chart))、ディスプレイの読み込みが完了します。次に、ディスプレイが「モニター」のコントロール コレクションに追加され、フォームが表示されます。

私が抱えている問題は、各チャート コントロールの読み込みに約 0.5 秒かかり、1 つの表示オブジェクトに約 75 個のチャート コントロールを含めることができることです。したがって、ロード時間を短縮するために、これらのチャートを並行して作成したいと思います。これを実現するために TPL メソッドを利用Parallel.ForEachしました。

私のコードは、「表示」オブジェクトのコンストラクター内で次のようになります。

public class DisplayControl : UserControl
{
    public DisplayControl()
    {
        var chartNames = new string[] { "chart1", "chart2", ... };
        var builtCharts = new ConcurrentBag<Chart>();

        // Create the chart objects in parallel
        Parallel.ForEach(chartNames, name =>
            {
                // The chart constructor creates the chart itself, which is a 
                // custom user control object (inherits UserControl), composed  
                // of other various WinForm controls like labels, buttons, etc.
                var chart = new Chart();
                chart.Name = name;
                builtCharts.Add(chart);
            }
        );

        // Clean up the charts and add them to "display's" control collection
        foreach(var chart in builtCharts)
        {
            // Do some unimportant modifications to the chart, synchronously
            ...

            this.Controls.Add(chart);
        }
    }
}

DisplayControl コンストラクターは、メイン フォーム Monitor によってメイン スレッドで呼び出され、DisplayControl インスタンス自体が Monitor の ControlCollection に追加されます。Monitor は、クラスのメソッドでMonitor.Show()あるを使用して表示されます。ShowForm

私が経験している主な問題は、次のように、DisplayControl コンストラクターが行でInvalidOperationException時折スローすることです。this.Controls.Add

System.InvalidOperationException: Cross-thread operation not valid: Control 'panel' accessed from a thread other than the thread it was created on.

これは、コンストラクターpanelで作成された単なるパネル WinForms コントロールであることに注意してください。Chart()

最後に、コードは約 90% の確率で問題なく動作しているように見えますが、これらのエラーはランダムに発生しているように見えます。エラーが発生した場合は、通常、コードをすぐに再実行するだけで機能します。

私の目標は、このエラーを排除し、これをすべてスレッドセーフにすることです。

4

1 に答える 1

2

関連するすべての操作はSystem.Windows.Forms、メイン スレッドで実行する必要があります。これには多くの疑問があります。ここのように。したがって、並列ループでグラフを作成するだけの場合は、それをそのままにしておいたほうがよいでしょうforeach

于 2013-10-30T21:05:22.527 に答える