วิธีรันงาน C# หรือเธรดเป็นระยะเวลา X

ฉันมีตรรกะทางธุรกิจเพื่อตรวจสอบเว็บเซอร์วิสว่าบริการนั้นยังมีอยู่หรือไม่

ฉันต้องการตรวจสอบซ้ำทุกๆ 5 นาทีเป็นเวลา 1 ชั่วโมงหลังจากเวลาเริ่มต้น

วิธีดำเนินการนี้ผ่านงานหรือเธรดหรือฟังก์ชันการรอ/อะซิงก์


person Abhishek Gupta    schedule 08.03.2013    source แหล่งที่มา
comment
คุณได้ลองอะไรไปแล้ว   -  person Mario S    schedule 08.03.2013
comment
ชื่อของคุณน่าสับสน... ฉันสงสัยว่าคุณต้องการโทรซ้ำทุกๆ X นาทีแทน... ลองดูคำถามที่คล้ายกัน - stackoverflow.com/questions/tagged/   -  person Alexei Levenkov    schedule 08.03.2013
comment
@Alexei ฉันไม่ต้องการทำสิ่งที่คุณคิดอย่างแน่นอน ฉันต้องการรันงานเป็นระยะเวลา X   -  person Abhishek Gupta    schedule 08.03.2013
comment
@ มาริโอจนถึงตอนนี้ฉันเพิ่งไล่งานที่รันไม่สิ้นสุดจนกระทั่งบริการ windows ของฉันทำงาน แต่ฉันต้องการไล่งานเหล่านั้นเพื่อบอกว่า 10 นาทีถัดไปหลังจาก 10 นาทีฉันต้องยิงงานใหม่และต้องการกำจัดงานก่อนหน้านี้   -  person Abhishek Gupta    schedule 08.03.2013
comment
ชื่อยังไม่ชัดเจนสำหรับฉัน แต่อย่างน้อยฉันก็เห็นความต้องการของคุณ... ฉันเดาว่าคุณคงประสบปัญหาในการค้นหาวิธีแก้ปัญหา - หากคุณไม่ต้องการให้ทำงานไม่สิ้นสุด/ตรวจสอบการหมดอายุอย่างต่อเนื่องและไม่ต้องการตัวจับเวลา มันเป็นเรื่องยาก จะทำอะไรสักอย่างหลังจากเวลาผ่านไปสักระยะหนึ่ง...   -  person Alexei Levenkov    schedule 08.03.2013


คำตอบ (2)


ขั้นแรก ตรวจสอบข้อกำหนดทางธุรกิจของคุณอีกครั้ง สิ่งนี้ทำให้คุณได้อะไรกันแน่? บริการเว็บอาจหายไปทันทีเมื่อใดก็ได้ ดังนั้นการที่คุณเพิ่งตรวจสอบไม่ได้หมายความว่าการโทรครั้งถัดไปของคุณจะสำเร็จ นี่เป็นเรื่องจริงสำหรับการสื่อสารเครือข่ายทั้งหมด

ดังนั้นความซับซ้อนของโค้ด "ของจริง" ของคุณจึงไม่ลดลงหากคุณมี "ตัวตรวจสอบ" แยกต่างหาก ประโยชน์เพียงอย่างเดียวของการออกแบบประเภทนี้คือการแจ้งเตือนด้วยภาพแก่ผู้ใช้ว่าพวกเขาสามารถมั่นใจได้อย่างสมเหตุสมผลว่าการโทรใช้บริการครั้งถัดไปจะสำเร็จ ถึงอย่างนั้น คุณอาจต้องการพิจารณาใหม่ เพราะมันสมเหตุสมผลเท่านั้น และผู้ใช้จะโกรธถ้าคุณโกหกพวกเขา

ที่กล่าวว่าคุณสามารถทำได้โดยใช้ Tasks ดังนี้:

private static async Task CheckAsync(CancellationToken token)
{
  // Check your web service.
  await CheckWebServiceAsync(token);

  // Wait 5 minutes.
  await Task.Delay(TimeSpan.FromMinutes(5), token);
}

...

var done = new CancellationTokenSource(TimeSpan.FromHours(1));
Task checkingTask = CheckAsync(done.Token);
// When checkingTask completes:
//   IsCanceled -> One hour passed with no errors.
//   IsFaulted -> The web service failed.
person Stephen Cleary    schedule 08.03.2013

โซลูชันเธรดมีลักษณะดังนี้:

public class WebserviceChecker {

    private int durationInHours = 1;
    public void setDuration(int value) { durationInHours = value; }

    private boolean _shutdown = false;

    private DateTime _startTime = null;
    // System.Windows.Forms.Timer
    private Timer _timer = null;

    public void CheckWebservice() {

        _startTime = DateTime.Now;
        _timer = new Timer();
        _timer.Tick += handleTimerTick;

        while(!_shutdown) {
            try {
                // do what ever you want to do for checking your webservice...
                // ...
            } catch (ThreadAbortedException ex) {
                // do cleanup, then
                //
                break;
            } catch (Exception ex) {
                Logger.Instance.log(LoggerLogType.Type.Err, ex.ToString());
            }
            // wait 5 secs (customize to your needs)
            Threading.Thread.Sleep(5000);
        }

        if(_shutdown) {
            // do some regular cleanup here...
        }

    } // public void CheckWebservice()

    public void Shutdown() {
        _shutdown = true;
    }

    private void handleTimerTick(Object sender, System.EventArgs e) {
        TimeSpan ts = _startTime .Subtract(DateTime.Now);
        if(ts.TotalHours >= durationInHours) {
            Shutdown();
        }
    }
}

และตอนนี้เริ่มเธรดพื้นหลังดังนี้:

WebserviceChecker _c = new WebserviceChecker();

Thread _watcher = new Thread(_c.CheckWebservice);
_watcher.IsBackground = true;
_watcher.Start();

สำหรับงานตามกำหนดการ ดูที่นี่: C# เริ่มงานที่กำหนดเวลาไว้

ฉันต้องการโซลูชันเธรดมากกว่าเนื่องจากการรับข้อมูลจากกระบวนการภายนอกนั้นซับซ้อนกว่าเล็กน้อย การซิงโครไนซ์ข้อมูลเธรดเข้ากับเธรดหลักของคุณนั้นง่ายกว่า คุณจะต้องมีกระบวนทัศน์เช่น IPC (Inter Process Communication) บน WCF โดยไปป์ที่มีชื่อหรือการสื่อสารซ็อกเก็ต ( TCP/UDP)

หากคุณต้องการคำแนะนำวิธีรับข้อมูลกลับจากเธรดของคุณ: คุณสามารถทำได้เช่น กำหนดเหตุการณ์ในคลาส WebserviceChecker ซึ่งคุณจะเพิ่มขึ้นเมื่อมีการเปลี่ยนแปลงสถานะของ WS ของคุณ

บางคำเกี่ยวกับสิ่งที่ IsBackground... หากคุณไม่ได้ตั้งค่าเธรดเป็นพื้นหลัง แอปพลิเคชันของคุณจะออกก็ต่อเมื่อทุกเธรดเบื้องหน้าออกจากวิธีการทำงานของเขาแล้ว เธรดพื้นหลังจะถูกยกเลิกโดยอัตโนมัติเมื่อแอปพลิเคชันปิดตัวลง

คำพูดของ ThreadAbortedException: ใน .NET เราได้รับสิทธิ์ในการยกเลิกเธรดอย่างหนัก กรอบงานจะเพิ่มข้อยกเว้นนี้ที่ตำแหน่งใดๆ ในวิธีการเธรดเพื่อออก หากคุณไม่จับมัน เธรดจะออกโดยไม่มีการล้างข้อมูล ดังนั้นเพียงแค่จับมันไว้และทำความสะอาดหน่วยความจำหรือทำงานบางอย่างให้เสร็จสิ้น คุณจะทำสิ่งนี้ที่นี่เช่นนั้น:

_watcher.Abort();

เชียร์เซธ :)

[แก้ไข] มีบทช่วยสอนการทำมัลติเธรดที่ดีที่ MSDN: http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx [/แก้ไข]

[แก้ไข] หากคุณต้องการใช้ System.Threading.Timer คุณต้องใช้การมอบหมาย System.Threading.TimerCallback ในคลาส Watcher ของคุณ จากนั้นคุณสามารถยกตัวอย่างตัวจับเวลาใหม่ด้วยจุดแทนเธรดพื้นหลัง ดู http://msdn.microsoft.com/de-de/library/system.threading.timercallback.aspx สำหรับรายละเอียดเพิ่มเติม [/แก้ไข]

person ceth    schedule 08.03.2013
comment
คลาส Timer ของคุณเป็นของ system.Threading หรือ system.Timers.Timer - person Abhishek Gupta; 08.03.2013
comment
System.Windows.Forms.Timer - person ceth; 08.03.2013