سؤال

أحاول استخدام نمط المنتج المستهلك المنتج لمعالجة بعض البيانات وحفظها. أنا أستخدم تلقائي تلقائي للإشارات بين الشيءين هنا هو الرمز الذي لدي

هنا هي وظيفة المنتج

 public Results[] Evaluate()
    {
        processingComplete = false;
        resultQueue.Clear();
        for (int i = 0; i < data.Length; ++i)
            {
                if (saveThread.ThreadState == ThreadState.Unstarted)
                    saveThread.Start();
               //-....
               //Process data 
               // 
                lock (lockobject)
                {
                    resultQueue.Enqueue(result);
                }

                signal.Set();
            }
            processingComplete = true;
        }

وهنا وظيفة المستهلك

   private void SaveResults()
    {
        Model dataAccess = new Model();

        while (!processingComplete || resultQueue.Count > 0)
        {
            if (resultQueue.Count == 0)
                signal.WaitOne();
            ModelResults result;
            lock (lockobject)

            {
                result = resultQueue.Dequeue();
            }
            dataAccess.Save(result);
        }
        SaveCompleteSignal.Set();
    }

لذا فإن مشكلتي هي أحيانا ناتجة عن indueue. لست متأكدا من ما أفعله خطأ لا ينبغي أن تكون الإشارة. Waitone () أعلاه من هذه الانتظار فارغة؟

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

المحلول

يمكنك التحقق من حساب قائمة الانتظار خارج سياق متزامن. نظرا لأن قائمة الانتظار ليست مؤلفة، فقد تكون هذه مشكلة (ربما تكون Enqueue في عملية العدولة العالية 1 ولكن لا يمكن تعويض أي عنصر)، وسوف يذهب خطأ بجدية إذا كنت تستخدم أكثر من مستهلك واحد على أي حال.

قد ترغب في قراءة مقالات الخيوط التي كتبها جوزيف الباحري، لديه أيضا عينة جيدة لمشكلتك إلى جانب حل "أفضل" بدون كائنات مزامنة نظام التشغيل.

نصائح أخرى

لديك مشاكل مزامنة نظرا لعدم وجود قفل مناسب.

يجب عليك قفل جميع الوصول إلى قائمة الانتظار، بما في ذلك الشيك العدد.

بالإضافة إلى ذلك، باستخدام thread.threadstate. بهذه الطريقة هي "فكرة سيئة". من مستندات MSDN ل ReadState:

"حالة الخيط ليست مصلحة فقط في سيناريوهات التصحيح. يجب ألا يستخدم الكود الخاص بك أبدا حالة مؤشر الترابط لمزامنة أنشطة المواضيع."

لا يمكنك الاعتماد على هذا كوسيلة للتعامل مع المزامنة. يجب إعادة تصميمه للتأكد من بدء الخيط قبل استخدامه. إذا لم يتم البدء، فما عليك سوى عدم تهيئة ذلك. (يمكنك دائما استخدام فحص NULL - إذا كان خيال الخيط، قم بإنشائه وبدء تشغيله).

عليك أن تضع قفل () حولها الكل مراجع إلى قائمة الانتظار. لديك أيضا بعض المشكلات حول تحديد المعالجة كاملة (في نهاية قائمة الانتظار، ستحصل على إشارة ولكن قائمة الانتظار ستكون فارغة).

public Results[] Evaluate()
{
    processingComplete = false;
    lock(lockobject) 
    {
        resultQueue.Clear();
    }
    for (int i = 0; i < data.Length; ++i)
    {
        if (saveThread.ThreadState == ThreadState.Unstarted)
            saveThread.Start();
       //-....
       //Process data 
       // 
        lock (lockobject)
        {
            resultQueue.Enqueue(result);
        }

        signal.Set();
    }
    processingComplete = true;
}

private void SaveResults()
{
    Model dataAccess = new Model();

    while (true)
    {
        int count;

        lock(lockobject)  
        {
            count = resultQueue.Count;
        }
        if (count == 0)
            signal.WaitOne();

        lock(lockobject)  
        {
            count = resultQueue.Count;
        }
        // we got a signal, but queue is empty, processing is complete
        if (count == 0)
            break;

        ModelResults result;
        lock (lockobject)
        {
            result = resultQueue.Dequeue();
        }
        dataAccess.Save(result);
    }
    SaveCompleteSignal.Set();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top