1

次の方法でどのようにパフォーマンスを向上させることができますか?

最初にいくつかの背景情報:

フォームと使用されるロジック (より深い層) の間のマッピングは、ディクショナリ CtrlLogicMapping に入れられます。

コントロールは複数のロジックを持つことができます (フォーム上の異なるコントロールなど)。

場合によっては、オブジェクトが 1 つの (独立した) 制御ロジックで既に使用されているかどうかを知る必要があります。

各ロジックには、1 つ以上のマップされたオブジェクト スコープを含めることができます。これは、サード パーティ ベンダーから提供され、db にマップされたオブジェクトに関する情報を含みます。

オブジェクトが使用されている場合、aLogic.ObjectScope.IsUsed(ObjectID) は true または false を返す可能性があります。

オブジェクトが含まれているかどうかを確認し、オブジェクトスコープにオブジェクトがあるとすぐに true を返すメソッドが必要です (他のオブジェクトスコープは処理する必要がなくなりました。オブジェクトスコープは複数のロジックに含めることができます。

すべてのフォームにロジックが必要なわけではなく (したがって、リストは null または空になる可能性があります)、すべてのロジックに objectscope が必要なわけではありません (リストが null または空になることもあります)。

InUse メソッドは、しばらく時間がかかるものです (テストでの InUse は 60 ~ 140 ミリ秒かかりました)。

そのため、InUse の呼び出しをできるだけ避け、可能な限り並列化したいと考えています。

反復ソリューション:

internal bool InUse (string ID_in){

        List<string> checked = new List<string>();

        if (null != frmLogicMapping && 0 < frmLogicMapping.Count)
        {
            foreach (List<Logic> logics in frmLogicMapping.Values)
            {
                if (null != logics && 0 < logics.Count)
                {
                    foreach (Logic aLogic in logics)
                    {
                        if (null != aLogic.ObjectScope)
                        {
                            if (!checked.Contains(aLogic.ObjectScope.ID)) 
                            {
                                // can take up to 140 ms
                                if (aLogic.ObjectScope.InUse(ID_in)) 
                                    return true;
                                checkeded.Add(aLogic.ObjectScope.ID);
                            }
                        }
                    }
                }
            }
        }
        return false;
   }

InUse==true がすぐに true を返す必要があり、他の処理が何も報告しないという停止基準でそれを麻痺させる方法はありますか?

または、 PLINQ で何らかの方法で記述できますか? PLINQ で null 値をどのように処理できますか? それとも、通常の LINQ の方が良い選択でしょうか? (null 値を処理する方法も?)

私がやりたかったことは次のようなものでした

        if (null != frmLogicMapping&& 0 < frmLogicMapping.Count)
        {
            var objectscopes = frmLogicMapping.Values
                .Where(logics != null && logics.Count > 0)
                .SelectMany(logic => logic.ObjectScope)
                .Where(logic.ObjectScope!= null).ToList();

            bool returnValue = false;
            Parallel.ForEach(objectscopes, objectScope=>
            {
                if (objectScope.IsDirtyObject(objectID))
                {
                    returnValue  = true;
                }
            });
            return returnValue  ;
        }

しかし、どういうわけか私はlinqステートメントを混同しています...また、並列foreachからすぐに戻る方法、または戻り値を揮発性としてマークする方法もわかりません

ありがとう、オフラー


これまでの解決策: Stephen Borg に感謝

 if (null != objectScopes && 0 < objectScopes .Count)
        {
            System.Threading.Tasks.Task<bool>[] tasks = new System.Threading.Tasks.Task<bool>[objectScopes.Count];

            for (int i = 0; i < objectScope.Count; i++)
            {
                int temp= i;
                tasks[temp] = System.Threading.Tasks.Task.Factory.StartNew(() => { return objectScopes[temp].InUse(ID_in); }
                    , System.Threading.Tasks.TaskCreationOptions.LongRunning);
            }

            System.Threading.Tasks.Task.WaitAll(tasks);

            if (tasks.Any(x => x.Result == true))
            {
                return true;
            }
        } 

        return false;
4

1 に答える 1

2

もう 1 つのオプションは、リスト リストを検証するメソッドを作成し、System.Threading.Tasks.Task を使用することです。タスク.aspx .

構造的には、これに似たことができます:

            Func DummyMethod = () =>{
                true を返します。
            };

            // タスクのリストを作成
            System.Threading.Tasks.Task[] タスク = 新しい System.Threading.Tasks.Task[2];

            // 最初のタスク
            var firstTask = System.Threading.Tasks.Task.Factory.StartNew(() => DummyMethod(), TaskCreationOptions.LongRunning);
            タスク[0] = 最初のタスク;

            // 2 番目のタスク
            var secondTask = System.Threading.Tasks.Task.Factory.StartNew(() => DummyMethod(), TaskCreationOptions.LongRunning);
            タスク[1] = 2番目のタスク;

            // すべて起動
            System.Threading.Tasks.Task.WaitAll(タスク);

            if (tasks.Any(x => x.Result)) {
                Console.Write("使用中!");
            }

あなたの場合、タスクの結果をループして、返された値のいずれかが true かどうかを確認する必要があります。利益は、すべてのリストが別々のスレッドで一度に実行されることです。

于 2013-06-10T08:27:13.657 に答える