سؤال

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

// member variable
private static readonly object timerLock = new object();
private bool found = false;


// elsewhere
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed = Timer_OnElapsed;
timer.Start();


public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
  lock(timerLock)
  {
    if (!found)
    {
      found = LookForItWhichMightTakeALongTime();
    }
  }
}
هل كانت مفيدة؟

المحلول

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

timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed += Timer_OnElapsed;
timer.AutoReset = false;
timer.Start();


public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
    if (!found)
    {
      found = LookForItWhichMightTakeALongTime();
    }
    timer.Start();
}

نصائح أخرى

وأنا عادة إيقاف الموقت أثناء معالجة ذلك، أدخل حاول / أخيرا كتلة، واستئناف الموقت عند الانتهاء.

إذا LookForItWhichMightTakeALongTime() سوف يستغرق وقتا طويلا، أود أن أقترح عدم استخدام System.Windows.Forms.Timer لأن ذلك سوف حبس موضوع UI ويمكن للمستخدم قتل طلبك أفكر أنه جمدت.

وماذا يمكن ان تستخدم هو BackgroundWorker (جنبا إلى جنب مع Timer إذا رغبت في ذلك).

public class MyForm : Form
{
  private BackgroundWorker backgroundWorker = new BackgroundWorker();

  public MyForm()
  {
    InitializeComponents();
    backgroundWorker.DoWork += backgroundWorker_DoWork;
    backgroundWorker.RunWorkerCompleted +=
                                backgroundWorker_RunWorkerCompleted;
    backgroundWorker.RunWorkerAsync();
  }

  private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
  {
    e.Result = LookForItWhichMightTakeALongTime();
  }

  private void backgroundWorker_RunWorkerCompleted(object sender,
                                             RunWorkerCompletedEventArgs e)
  {
    found = e.Result as MyClass;
  }
}

ويمكنك الاتصال RunWorkerAsync() من أي مكان تريد، حتى من Timer إذا كنت تريد. وفقط للتأكد من معرفة ما اذا كان BackgroundWorker قيد التشغيل بالفعل منذ يدعو RunWorkerAsync() عندما يكون تشغيل سوف بطرح استثناء.

private void timer_Tick(object sender, EventArgs e)
{
  if (!backgroundWorker.IsBusy)
    backgroundWorker.RunWorkerAsync();
}
timer.enabled = false

أو

timer.stop();

و

timer.enabled = true

أو

timer.start();

وأنا استخدم System.Threading.Timer مثل ذلك

 class Class1
    {
        static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1));

        private static void DoSomething(object state)
        {
            timer = null; // stop timer

            // do some long stuff here

            timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
        }



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