سؤال

لقد كنت أقرأ على .NET الخيوط وكان يعمل على بعض الكود الذي يستخدم manualresetevent.. وبعد لقد وجدت الكثير من عينات التعليمات البرمجية على الإنترنت. ومع ذلك، عند قراءة الوثائق ل whithandle., رأيت ما يلي:

waithandle تنفذ نمط التخلص من النمط. انظر تنفيذ الانتهاء والتخلص لتنظيف الموارد غير المدارة.

لا يبدو أن أيا من العينات تدعو. close () على كائنات manualresetevent التي تنشئها، حتى لطيف العودية والتزامن مقالة من بلوق pfxteam (يحرر - هذا لديه كتلة باستخدام فاتني). هل هذا إشراف مثالي فقط، أم لا يحتاج؟ أنا فضولي لأن waithandle "يثبط الكائنات الخاصة بنظام التشغيل،" لذلك يمكن أن يكون هناك تسرب الموارد بسهولة.

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

المحلول

بشكل عام، إذا كان كائن ينفذ IDisposable يفعل ذلك لسبب ما ويجب أن تتصل Dispose (أو Close, ، كما قد تكون الحالة). في المثال أنت موقع، ملفوفة manualresetevent داخل using بيان، والتي سوف "تلقائيا" التعامل مع الدعوة Dispose. وبعد في هذه الحالة، Close مرادف Dispose (وهذا صحيح في معظم IDisposable التطبيقات التي توفر Close طريقة).

الرمز من المثال:

using (var mre = new ManualResetEvent(false))
{
   ...
}

يتوسع إلى

var mre = new ManualResetEvent(false);
try
{
   ...
}
finally
{
   ((IDispoable)mre).Dispose();
}

نصائح أخرى

لقد أحالت مؤخرا مقتطفات من C # 4.0 باختصار: المرجع النهائي بقلم جوزيف الباهر، بن البحري. في الصفحة 834، في الفصل 21: خيوط هناك قسم يتحدث عن هذا.

التخلص من مقابض الانتظار

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

يتم إصدار مقابض الانتظار تلقائيا عند تفريغ مجال التطبيق.

يتم التعامل مع إغلاق داخل تخلص من depalresetevent، وهذا ما يسمى ببيان "استخدام".

http://msdn.microsoft.com/en-us/library/yh598w02٪28VS.100٪29.aspx.

سوف تلاحظ الكود

 using (var mre = new ManualResetEvent(false))
 {
    // Process the left child asynchronously
    ThreadPool.QueueUserWorkItem(delegate
    {
        Process(tree.Left, action);
        mre.Set();
    });

    // Process current node and right child synchronously
    action(tree.Data);
    Process(tree.Right, action);

    // Wait for the left child
    mre.WaitOne();
}

يستخدم الكلمة الأساسية "باستخدام". يستدعي هذا تلقائيا طريقة التخلص عند الانتهاء حتى إذا أرقى التعليمات البرمجية استثناء.

لقد استخدمت ManualResetEvent كثيرا ولا أعتقد أنني استخدمت ذلك من أي وقت مضى داخل طريقة واحدة - إنها دائما مجال مثيل لفئة. لذلك using() في كثير من الأحيان لا ينطبق.

إذا كان لديك حقل مثيل فئة هو مثيل ManualResetEvent, ، جعل فصولك التنفيذ IDisposable وفيك Dispose() طريقة الاتصال ManualResetEvent.Close(). وبعد ثم في جميع تفضيلات الفصل الخاص بك، تحتاج إلى استخدام using() أو جعل تنفيذ الفئة المحتوية IDisposable وكرر، وكرر ...

إذا كنت تستخدم ManualResetEvent مع طرق مجهولة، من الواضح أنها مفيدة. ولكن كما ذكر SAM أنه يمكن تمريرها في كثير من الأحيان إلى العمال، ثم اضبط وأغلقت.

لذلك أود أن أقول ذلك يعتمد على سياق كيف تستخدمه - msdn waithandle.waitall () نموذج الكود لديه مثال جيد على ما أعنيه.

إليك مثال بناء على عينة MSDN من كيفية إنشاء WATHATHALS مع using البيان استثناء:

system.objectdispusesception.
"تم إغلاق مقبض آمن"

const int threads = 25;

void ManualWaitHandle()
{
    ManualResetEvent[] manualEvents = new ManualResetEvent[threads];

    for (int i = 0; i < threads; i++)
    {
        using (ManualResetEvent manualResetEvent = new ManualResetEvent(false))
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ManualWaitHandleThread), new FileState("filename", manualResetEvent));
            manualEvents[i] = manualResetEvent;
        }
    }

    WaitHandle.WaitAll(manualEvents);
}

void ManualWaitHandleThread(object state)
{
    FileState filestate = (FileState) state; 
    Thread.Sleep(100);
    filestate.ManualEvent.Set();
}

class FileState
{
    public string Filename { get;set; }
    public ManualResetEvent ManualEvent { get; set; }

    public FileState(string fileName, ManualResetEvent manualEvent)
    {
        Filename = fileName;
        ManualEvent = manualEvent;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top