سؤال

لقد كتبت مكتبة مجمعة لمكتبة WinMM تعرض فئات WaveOut و WaveIn لغرض تسجيل وتشغيل تدفقات الصوت الأولية.

كل شيء يعمل بشكل رائع، ولكن من أجل متابعة مواصفات نظام التشغيل حول كيفية التعامل مع المخازن المؤقتة النهائية، قمت بإضافة موضوع يقوم بإلغاء إعداد المخازن المؤقتة وتحرير الذاكرة.لقد قمت أيضًا بإيقاف كل المزامنة، بحيث تكون الفئات صلبة وآمنة.

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

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

أي أفكار، أو الأخطاء المعروفة؟

ملاحظة:لا يبدو أن هذا يحدث على نظام Quad Core في نظام التشغيل Vista، ولكنه يحدث على جهاز Dual Core في نظام XP pro.

تحرير 1:أنا على استعداد تام لكشف كود المصدر الكامل، بمجرد أن أقوم بتحميله وترخيصه على codeplex، إذا كان ذلك سيساعد أي شخص.

تحرير 2:المكتبة المنشورة على CodePlex: http://winmm.codeplex.com/

فيما يلي فكرة عن أسباب المشكلة:

public partial class MainView : Form
{
    private WaveIn waveIn = new WaveIn(WaveIn.WaveInMapperDeviceId);
    private WaveOut waveOut = new WaveOut(WaveOut.WaveOutMapperDeviceId);

    public MainView()
    {
        InitializeComponent();

        WaveFormat format = WaveFormat.Pcm44Khz16BitMono;

        waveOut.Open(format);

        waveIn.DataReady += new EventHandler<DataReadyEventArgs>(WaveIn_DataReady);

        // Tweaking these values affects the internal buffering thread.
        // Setting too small of a QueueSize with too small of a BufferSize
        //  will cause buffer underruns, which will sound like choppy audio.
        waveIn.BufferQueueSize = 200;
        waveIn.BufferSize = 64;

        waveIn.Open(format);

        waveIn.Start();
    }

    void WaveIn_DataReady(object sender, DataReadyEventArgs e)
    {
        if (waveOut != null)
        {
            lock (waveOut)
            {
                // We have to check for null after the lock,
                //  because waveOut may have been disposed
                //  inside another lock.
                if (waveOut != null)
                {
                    waveOut.Write(e.Data);
                }
            }
        }
    }

    private void MainView_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (waveIn != null)
        {
            lock (waveIn)
            {
                waveIn.Dispose();
                waveIn = null;
            }
        }

        if (waveOut != null)
        {
            lock (waveOut)
            {
                waveOut.Dispose();
                waveOut = null;
            }
        }
    }
}
هل كانت مفيدة؟

المحلول

أود أولاً إنشاء منفصل object التي لقفل.من المفترض أن يؤدي ذلك إلى تبسيط الكثير من منطق التحقق من القيمة الخالية (بحوالي النصف منذ قيامك بالتحقق قبل القفل وبعده).

ثانية، Dispose لن يقوم بتعيين المتغير الخاص بك على null, ، لذلك ستظل عمليات التحقق الأخرى تمر لأن الكائن ليس فارغًا، بل تم التخلص منه فقط.لذلك سأفعل

waveOut.Dispose();
waveout = null;

للتأكد من أنه تم تعيينه بشكل صريح على القيمة الخالية.

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