سؤال

أنا في VS2008 مع إطار الكيان. أنا في الوصول إلى الكائنات من قاعدة البيانات باستخدام ESQL للمكان في الوظيفة. أقوم بتمرير طن من المعرفات إلى عبارة SELECT حتى أقطعها إلى مجموعات من 800. ثم دمج النتائج معا من كل قطعة. هدفي هو الحصول على نتائج لكل قطعة بالتوازي، بدلا من الانتظار بشكل متزامن. لقد قمت بتثبيت الإطار التفاعلي وأنا متأكد من أنني بحاجة للاستفادة من forkjoin. ومع ذلك، لا يمكنني معرفة كيفية تحويل هذه الوظيفة لاستخدامه. إليك الرمز الموجود الخاص بي:

    public static IList<TElement> SelectWhereIn<TElement, TValue>(this ObjectContext context, string fieldName, IList<TValue> idList)
    {
        var chunkedIds = idList.Split(CHUNK_SIZE);
        string entitySetName = typeof(TElement).Name + "Set";
        var retList = new List<TElement>();
        foreach (var idChunk in chunkedIds)
        {
            string delimChunk = string.Join(",", idChunk.Select(x => x.ToString()).ToArray());
            ObjectQuery<TElement> query = context.CreateQuery<TElement>("SELECT VALUE x FROM " + entitySetName + " AS x");
            query = query.Where("it." + fieldName + " IN {" + delimChunk + "}");
            retList.AddRange(query);
        }
        return retList;
    }

شكرا!

عدل >>> قمت بتعديل التعليمات البرمجية لاستخدام رجل فقير على النحو التالي:

    public static IList<TElement> SelectWhereIn<TElement, TValue>(this ObjectContext context, string fieldName, IList<TValue> idList)
    {
        var chunkedIds = idList.Split(CHUNK_SIZE);
        string entitySetName = typeof(TElement).Name + "Set";
        var chunkLists = new List<IEnumerable<TElement>>();
        Parallel.ForEach(chunkedIds, idChunk =>
        {
            string delimChunk = string.Join(",", idChunk.Select(x => x.ToString()).ToArray());
            ObjectQuery<TElement> query = context.CreateQuery<TElement>("SELECT VALUE x FROM " + entitySetName + " AS x");
            query = query.Where("it." + fieldName + " IN {" + delimChunk + "}");
            chunkLists.Add(query.ToList());
        });
        var retList = new List<TElement>();
        foreach (var chunkList in chunkLists)
        {
            retList.AddRange(chunkList);
        }
        return retList;
    }

عملت كبيرة في المرة الأولى. ولكن في المرة الثانية، ركضت ذلك، حصلت على هذا الخطأ:

لم يتم إغلاق الاتصال. الحالة الحالية للاتصال هي الاتصال. الوصف: حدث استثناء غير معالج أثناء تنفيذ طلب الويب الحالي. يرجى مراجعة تتبع المكدس لمزيد من المعلومات حول الخطأ وأين نشأ في التعليمات البرمجية.

تفاصيل الاستثناء: System.invalidoperationException: لم يتم إغلاق الاتصال. الحالة الحالية للاتصال هي الاتصال.

خطأ المصدر:

السطر 49: foreach (var iAsyncresult في قائمة الناتج) السطر 50: {Line 51: del.endinvoke (IAsyncresult)؛ الخط 52: IAsyncresult.asyncwaithandle.close ()؛ الخط 53:}

إنه أمر مثير للاهتمام، B / C EMRE (مؤلف المكتبة) لديه تحرير إلى منصبه الأصلي الذي يتحدث عن كيفية إضافة تلك الأسطر من التعليمات البرمجية لسلامة إضافية. هل أنا أستخدمه بشكل صحيح؟ أو كان v1 أكثر أمانا بعد كل شيء؟

هل كانت مفيدة؟

المحلول

VS2010 هل لديه ذلك مع بلينك. باستخدام الامتدادات AsParallel().WithDegreeOfParallelism(nbProcessors) سوف تفعل ما تحتاجه.

مع VS2008، لقد استخدمت ضعف الرجل الموازي. Ifteach Imerator في الماضي عندما كنت أحاول العمل حول عنق الزجاجة في الأداء، حاول أن أعطها طلقة.

تحرير: عند رد الفعل على الخطأ الذي أضفته، فقد تكون طلقة عشوائية في سياقات الظلام، ولكنها منفصلة لكل موضوع؟ مثل ذلك:

Parallel.ForEach(chunkedIds, idChunk =>
    {
        ObjectContext context = new MyContext(connStr);//depending what's your config
                                                       // like, with or w/o conn string

        string delimChunk = string.Join(",", idChunk.Select(x => x.ToString()).ToArray());
        ObjectQuery<TElement> query = context.CreateQuery<TElement>("SELECT VALUE x FROM " + entitySetName + " AS x");
        query = query.Where("it." + fieldName + " IN {" + delimChunk + "}");
        chunkLists.Add(query.ToList());
    });

قد تضطر إلى تعديل بعض الأشياء (مثل أخذ سلسلة connextion من السياق الممتد إلى إنشاء سياقات جديدة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top