سؤال

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

دعونا نأخذ مثالا على ذلك :

  1. جهاز ضبط الوقت المنقضي ، لذلك فإن هذه الطريقة ودعا.هذه المهمة يمكن أن يستغرق بضع ثانية.

  2. بعد أن ينقر المستخدم على بعض زر ، والتي ينبغي أن تؤدي إلى بنفس المهمة :BAM.فإنه لا يفعل شيئا لأن الأسلوب هو قيد التشغيل بالفعل.

أنا استخدام الحل التالي :

public void DoRecurentJob()
{
    if(!Monitor.TryEnter(this.lockObject))
    {
        return;
    }

    try
    {
        // Do work
    }
    finally 
    {
        Monitor.Exit(this.lockObject);
    }
}

حيث lockObject أعلن مثل هذا:

private readonly object lockObject = new object();

تحرير :لن يكون هناك مثيل واحد فقط من الكائن الذي يحمل هذا الأسلوب لذا تحديث قفل كائن أن يكون غير ثابت.

هل هناك طريقة أفضل للقيام بذلك ؟ أو ربما هذا هو مجرد خطأ لأي سبب من الأسباب ؟

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

المحلول

هذا يبدو معقولا إذا كنت مهتما فقط في عدم وجود طريقة تشغيلها في نفس الوقت.لا يوجد شيء يمنع من تشغيل فورا بعد بعضها البعض ، ويقول أن ضغطت على الزر نصف جزء بعد على توقيت تنفيذها الشاشة.Exit().

وبعد قفل وجوه للقراءة فقط ثابت أيضا معنى.

نصائح أخرى

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

هناك إشارات يبني هذا العمل ، ولكن المثال الخاص بك يبدو أنه لا حيلة و بطريقة بسيطة وواضحة.

ثانوية أحمق:إذا كان lockObject متغير غير ثابت ، ثم "هذه.lockObject" لا ترجمة.كما يبدو غريبا بعض الشيء (و يجب أن تكون على الأقل بشكل كبير موثقة) أنه على الرغم من أن هذا هو أسلوب مثيل ، فقد بوضوح نوع نطاق السلوك أيضا.ربما تجعل من أسلوب ثابت الذي يأخذ مثيل كما المعلمة ؟

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

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

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

public class MyClass
{

  // Used as a lock context
  private readonly object myLock = new object();

  public void DoSomeWork()
  {
    lock (myLock)
    {
      // Critical code section
    }
  }
}

إذا كان التطبيق الخاص بك يتطلب قفل span جميع حالات MyClass يمكنك تحديد قفل سياق ثابت الميدانية:

private static readonly object myLock = new object();

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

تذكر أنه يمكنك دائما ثابت syncronous طريقة الحماية أو خاصة ، مما يجعلها مرئية فقط إلى حالات الطبقة.

public class MyClass
{ 
    public void AccessResource()
    {
        OneAtATime(this);
    }

    private static void OneAtATime(MyClass instance) 
    { 
       if( !Monitor.TryEnter(lockObject) )
       // ...

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

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

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

[MethodImpl(MethodImplOptions.Synchronized)] 
public void OneAtATime() { }

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

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

https://codereview.stackexchange.com/questions/16150/singleton-task-running-using-tasks-await-peer-review-challenge

private queued = false;
private running = false;
private object thislock = new object();

void Enqueue() {
    queued = true;
    while (Dequeue()) {
        try {
            // do work
        } finally {
            running = false;
        }
    }
}

bool Dequeue() {
    lock (thislock) {
        if (running || !queued) {
            return false;
        }
        else
        {
            queued = false;
            running = true;
            return true;
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top