PDA

View Full Version : آموزش: استفاده از Task Scheduler یا windows service برای وظایف زمان بندی شده



RezaNrzdh
جمعه 20 تیر 1393, 18:54 عصر
سلام.
شاید برای خیلی ها پیش اومده باشه که بخوان یک سری وظایف از پیش تعیین شده رو در web app خودشون اجرا کنن، میخوام با چند مثال این روش رو توضیح بدم

حالاتی وجود داره وقتی یه برنامه تحت وب asp.net به اجرای یک سری کد در زمان های مشخص نیاز پیدا میکنه. که میتونه ایجاد برخی گزارش های روزانه ، ایمیل های یادآوری و تبلیغاتی به کاربرا در زمان تعیین شده ، آنلاین نگه داشتن وب سایت به وسیله صدا کردن صفحات ساختگی هر 10 دقیقه یک بار ، بک آپ گیری از دیتابیس و غیره باشه.
خود asp.net راه حلی ساده و قابل اعتماد برای این مشکل نداره. اگر بخوایم فقط از asp.net استفاده کنیم برای اجرای وظایف زمانبندی شده ، باید Scheduled task رو شبیه سازی کنیم که در موارد ساده به خوبی کار میکنه.
و در ضمن این تنها راه حلیه که شما پیش رو دارین وقتی از هاست اشتراکی استفاده میکنید (البته میگن Quartz.NET توی هاست اشتراکی هم خوب کار میکنه)

آموزشی که میخوام بذارم تو فروم به دو قسمت تقسیم میشه


استفاده از Task Scheduler یا windows service برای وظایف زمان بندی شده

Scheduled task در asp.net (به زودی لینک آپدیت میشود)

برای اینکه آشنا بشین با شبیه سازی Scheduled task توسط asp.net آموزش دوم رو هم دنبال کنید

تنها مشکلی که با asp.net هست فقط روی متد هاشه، یعنی وقتی برنامه asp.net به دلایل متعدد ریستارت بشه یا حتی متوقف بشه ،تمام اجراهای scheduled task هم به تاخیر میفتن یا حتی اصلا دیگه اجرا نمیشن.
به همین دلیل، برای اجرای وظایف مهم که در یک زمان مشخص باید اجرا بشن، توسعه دهنده ها معمولا روش های قابل اعتماد تری رو انتخاب میکنن مثل استفاده از windows service یا task scheduler خود ویندوز.
اگر شما سرور اختصاصی برای web app خودتون داشته باشید، خب میتونید windows service رو روی سرور نصب کنید تا وظایف زمانبندی شده رو اجرا کنه. در سرور های اشتراکی، کاربرها معمولا نمیتونن windows service رو نصب کنن، اما شما میتونید windows service رو از روی کامیپوتر های دیگه ی سرور اجرا کنید که به صورت اتوماتیک یک webservice جدید رو براتون ایجاد میکنه.

بریم سر وقت کد نویسی:


using System.ServiceProcess;

namespace TestWindowsService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
}

protected override void OnStop()
{
}
}
}


windows service خیلی قابل اعتماد تر از scheduled taskیه که فقط با asp.net ساخته شده. چون برنامه asp.net به دلایل مختلفی احتمال داره متوقف یا ریستارت بشه. پس اگه برنامه asp.net شما در یه برهه زمانی به هر دلیلی کار نکنه، این به این معنی هست که کارهای زمان بندی شما هم اجرا نخواهند شد. (بدبختی ها از اینجا شروع میشه)

دلایل مختلف زیادی وجود داره که یک برنامه asp.net ریستارت میشه، میتونه به خاطر تغییرات در web.config ، تغییرات در فولدر bin ، تغییرات در global.asax ، تغییرات در app_global_resources یا فولدر app_local_resources باشه، میتونه تغییرات به خاطر فولدر app_code هم باشه. حتی گاهی به خاطر اینکه در بعضی دوره های زمانی سایت هیچ بیننده ای نداره (معمولا بازه های زمانی شب) وب سرور برنامه asp.net رو شات دان میکنه در نتیجه وظایف زمان بندی شده دیگه اجرا نمیشن، تا یه بیننده وارد سایت بشه و وب سرور برنامه asp.net رو دوباره اجرا کنه.

اجرای کد ها در win service و متدهای asp.net معمولا شبیه به هم. توی آموزش دوم (Scheduled task در asp.net) دو مثال وجود داره برای تکرار دوره های زمانی، یکی Timer و دیگری Thread. که دقیقا این ایده ها کاملا مفید و قابل استفاده در windows service هست. در واقع به جای استفاده از application_start در global.asax، از OnStart متد برای ساخت حلقه تکرار شونده استفاده میشه.

کد زیر مثالی از windows serviceـه که از thread برای ساخت کلاسی استفاده میکنه که به صورت دوره ای متد ScheduledTask رو صدا میزنه


using System.ServiceProcess;
using System;
using System.Threading;

namespace TestWindowsService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
// وقتی ویندوز سرویس اجرا بشه ترد ها ساخته میشن
ThreadStart tsTask = new ThreadStart(TaskLoop);
Thread MyTask = new Thread(tsTask);
MyTask.Start();

}

static void TaskLoop()
{
// توی این مثال به وسیله while حلقه به صورت بینهایت اتفاق میفته
// شما میتونید یک سری پارامتر ها رو بهش اضافه کنید اگه نیاز دارید که گاهی سرویس متوقف یا ریستارت بشه
while (true)
{
// اول متد اجرا میشه
ScheduledTask();

// بعد از اجرای متد یه زمان مشخصی رو منتظر میمونه تا دوباره متد بالا رو اجرا کنه...در این کد هر یک ساعت یک بار اجرا میشه
System.Threading.Thread.Sleep(TimeSpan.FromHours(1 ));
}
}

static void ScheduledTask()
{
// اینجا اتفاقی که هر یک ساعت یک بار باید اتفاق بیفته رو بنویسید...میتونه صدا کردن کلاس های دیگه در لایه های دیگه و غیره باشه

}

protected override void OnStop()
{
//
}
}
}


متد OnStop وقتی اجرا میشه که سرویس متوقف شده باشه...متد OnStop خیلی میتونه مفید باشه و با یک پیغام شمارو آگاه کنه وفتی که به هر دلیلی وظایف زمان بندی شده دیگه اجرا نمیشن.حتی شما میتونید خطا هارو در فایل log به وسیله این متد بنویسید.

کد زیر مثالی از windows serviceـه که از timer استفاده میکنه


using System.ServiceProcess;

namespace TestWindowsService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
// به صورت دینامیک تایمر ایجاد میشه
System.Timers.Timer timScheduledTask = new System.Timers.Timer();

// وقفه روی میلی ثانیه تنظیم شده,
// در این مورد، تایمر روی دقیقه تنظیم شده...هر یک دقیقه یک بار
timScheduledTask.Interval = 60 * 1000;

timScheduledTask.Enabled = true;

timScheduledTask.Elapsed +=
new System.Timers.ElapsedEventHandler(timScheduledTask _Elapsed);
}

void timScheduledTask_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// اجرای وظیفه
FirstTask();
}

void FirstTask()
{
// اینجا ما کدی نیاز دریم تا به صورت دوری ای اجرا بشه

}

protected override void OnStop()
{
//
}
}
}


حالا سوالی که مطمعنا پیش میاد اینه که:
ما باید از Thread برای وظایف زمانبندی شده استفاده کنیم یا timer؟

به صورت تئوریک هر دو مثال بالا (ترد و تایمر) یک کار رو انجام میدن.توی این تمرین کلاس timer کارایی بهتری داره. استفاده از thread.sleep غالبا به عنوان طراحی بد و اتلاف دهنده منابع تلقی میشه. از طرف دیگه مشکلات دیگه ای که ممکنه گریبان گیر شما بشه اینه که اگه نیاز داشته باشید windows service رو متوقف کنید ، Timer سریع تر متوقف میشه اما Thread در بازه زمانی sleep سرویس رو غیر قایل دسترس میکنه (Frozen) و شما نمی تونید سرویس رو متوقف کنید.
همچنین کلاس تایمر برای اندازه گیری زمان هست و دقیق تر کار میکنه نسبت به Threadی که بیشتر از اون چیزی که شما مشخص کردین صبر میکنه.انتخاب کردن یکی از این دوتا خیلی مهمه وقتی که شما با بازه های زمانی کم سر و کار دارید.

برای اغلب موارد ، هر دو روش احتمالا خوب کار میکنن و پیاده سازی هر دو هم بسیار آسونه... اما به دلیل مزیت های کوچیکی که قبلا بهش اشاره کردم من timer رو ترجیح میدم.

انجام وظایف زمانبندی شده با استفاده از windows task scheduler و Net console application.

روشی که در windows task scheduler استفاده میشه خیلی شبیه به windows service هست.شما همچنین نیاز به دسترسی کامل به وب سرور دارید. پس این روش برای کسایی که از هاست های اشتراکی استفاده میکنن غیر ممکنه. windows task scheduler به عنوان روشی برای انجام وظایف زمانبندی شده با تنظیمات و توانایی های زیاد ساخته شد. کار باهاش خیلی راحت چون از یه UI خیلی ساده بهره میبره.
windows task scheduler سریع تر از ساخت windows service از ابتدا هست. windows task scheduler دارای انتخاب هایی مثه

اجرای برنامه یا اسکریپت
فرستادن ایمیل
نمایش پیغام

اگر وظایف زمانبندی تعیین شده توسط ما نیاز که یک صفحه asp.net رو صدا بزنه ، پس شما باید به صورت غیر مستقیم این کار رو انجام بدید...توی ایم مورد بعضی از توسعه دهنده ها پیشنهاد میکنن وظیفه زمانبندی شده ما بهتر بیاد IE رو باز کنه و یه URL رو به عنوان پارامتر بهش اضافه کنه...یه چیزی مثه خط زیر:


iexplore http://www.yourdomain.com/ScheduledTask.aspx

به درستی کار میکنه. windows task scheduler میره IE رو باز میکنه و صفحه aspx مورد نظر رو لود میکنه...اما مشکل جایی اتفاق میفته که لود صفحه تموم شده ، حالا به کسی نیاز داریم که صفحه رو ببنده. حالا مشکل بزرگتر هم میشه وقتی که وظایف ما میبایست در فواصل زمانی کوتاهی اتفاق بیفته...این روش حتی ممکن IE رو نابود کنه :D

اما به نظر من این راه خوبی نیست. من فکر میکنم بهتر باشه یه برنامه کنسولی کوچیک نوشته بشه با C#‎‎‎‎‎‎ یا VB.NET ، که میتونه به وسیله کلاس System.Net.WebClient مطمئن بشه درخواست انجام شده و وقتی وظیفه کارش رو تموم شد بسته بشه.

پس بیاین این برنامه رو بسازیم.
یه پروژه Console Application رو ایجاد کنید و نامش رو مثلا بذارید WebTask...کد زیر خیلی ساده هست.


using System;
using System.Text;
using System.Net;

namespace WebTask
{
class Program
{
static void Main(string[] args)
{
// وب کلاینت ساخته میشه
WebClient wc = new WebClient();

string WebURL = args[0];
UTF8Encoding encUTF8 = new UTF8Encoding();
string ReturnedData = "";

try
{
// صفحه یا وب سرویس صدا زده میشه و اطلاعات برگشتی خونده میشه
ReturnedData = encUTF8.GetString(wc.DownloadData(WebURL));

//علاوه بر این ما میتونیم یک سری اعمال با داده های برگشتی انجام بدیم
// مثلا چک کنه اگر وظایف به درستی انجام شد،یک سری آنالیز رو انجام بده

}
catch (Exception ex)
{
// اگه یه چیزی اشتباه شد
// اطلاعاتی در مورد اون استثنا رو در داخل فایل log ، دیتابیس بنویسه یا
// ایمیای رو ارسال بکنه.

}
}
}
}


حالا شما میتونید از این برنامه در windows task scheduler استفاده کنید و صداش بزنید.

حالا باز یه سوال پیش میاد:
من باید از کدوم یکی استفاده کنم؟ windows task scheduler یا Windows service ؟

windows task scheduler و windows service روش های مشابهی دارن.هر دوی اونها نیاز به درسترسی کامل به سرور دارن.پس احتمال داره شما نتونید از اونها در هاست های اشتراک استفاده کنید.
این دو روش برای سایت هایی که روی سرور های اختصاصی هستن و بازدید بالایی دارن پیشنهاد میشه.اگه بخوام این دو رو در کسب و کار مقایسه بکنم، باید بگم windows task scheduler نیازمند کار کمتریه ، تازه شما نیاز نیست یه ویندوز سرویس جدید بسازید. windows task scheduler برنامه ایه که توانایی های زیادی داره. در حقیقت windows task scheduler هم مثل windows service در پشت صحنه اتفاق میفته ، به وسیله admin قایل استفاده هست و میتونید در هر زمانی وظایفی رو بهش اضافه کنید یا تغییرش بدید.

وقتی بخواین از windows service استفاده کنید، نیاز دارید یک سری کد برای وظایفتون بنویسید، همینطور یه سوریس جدید رو از اول بسازید. پیاده سازی و تستش دقیقا همون منطقیه که در windows task scheduler هست ، تازه windows task scheduler خودش یه windows serivce هست. و بر فرض اینکه شما یه GUI برای windows serviceتون ساختید در نهایت به چیزی رسیدید که از قبل بر روی کامپیوتر شما بوده :)
با این وجود به نظر میرسه در بیشتر موارد داریم وقتمون رو هدر میدیم. پس به شخصه میگم windows task sheduler باید انتخاب اول شما باشه چون پیاده سازیش خیلی سریع و ساده هست. وقتی که windows task scheduler نتونه نیاز های پروژه رو برآورده کنه اونوقت windows service انتخاب بعدی شماست.

شما باید بدونید که windows task scheduler هم دارای اشکالاتیه، کمترین وقفه در اون 1 دقیقه هستش، پس اگه وظایف شما باید هر 10 ثانیه یک بار اتفاق بیفته، بهتره از windows service استفاده کنید.

وظایف زمانبندی شده در asp.net به وسیله DotNetPanel ، Plesk یا Helm

بیشتر وب سرور ها برنامه های مدیریت هاست دارن مثل donetpanel یا plesk یا helm و غیره...برنامه هایی مثل این کلی امکانات دارن برای اینکه نگهداری وب سایت آسون تر بشه ، اونها همچنین از وظایف زمانبندی شده پشتیبانی میکنن.
توجه داشته باشید که گاهی scheduled task در dotnetpanel یا heml ممکن توسط ارائه دهنده هاست غیر فعال باشه.اونها معمولا این کار رو به این دلیل انجام میدن تا در منابع سرور صرفه جویی کرده باشن. اما اگه این گزینه در وب سرور شما فعال باشه، میتونه راه حلی سریع و قابل اعتماد برای شما باشه.

در انتها

همانطور که دیدید، راه های خیلی زیادی برای پیداه سازی scheduled task در برنامه های asp.net وجود داره. در این آموزش سعی کردم روش های بیرونی رو مثل windows service ، windows task scheduler و برنامه های هاست رو توضیح بدم.
به عنوان یه روش امن من windows service رو پیشنهاد میکنم اما این بدان معنا نیست که توی همه موارد بخوام از windows service استفاده کنم.
ساختن و به خصوص نگه داری از windows service میتونه زمان بر باشه، در اغلب موارد مشکلات میتونه با اضافه کردن یه scheduled task در helm حل بشه.پس بهترین روش رو برای موارد خاص مربوط به خودتون انتخاب کنید.

موفق باشید.


-------------
منبع: http://www.beansoftware.com/ASP.NET-Tutorials/Task-Scheduler-Windows-Service.aspx

alizx.1370
دوشنبه 23 تیر 1393, 12:19 عصر
agha dastet dard nakone faghat vase tashakar az postet login kardam ;)

RezaNrzdh
دوشنبه 23 تیر 1393, 15:41 عصر
agha dastet dard nakone faghat vase tashakar az postet login kardam ;)
خواهش میکنم دوست عزیز... :لبخندساده: امیدوارم به کارتون اومده باشه

lastmory
سه شنبه 12 خرداد 1394, 16:07 عصر
سلام ممنون از پست مفیدتون
من هم یک ویندوز سرویس نوشتم برای زمانبندی اما مشکلات زیر رو دارم
1 - درسته که اتوماتیک هستش اما بعد از لاگین شدن کاربر استارت نمیشه به صورت اتوماتیک
2 - توی ویندوز سون برای اینکه پیغام رو نشون بده اول این پیغام میاد براش اما توی ویندوز XP مشکلی نداره
131891