Geçenlerde bir sohbet sırasında arkadaşım ile yapılıp-yapılamayacağı hakkında uzunca tartıştığımız bir konu oldu. "Normal web hosting paketlerinde, belirli aralıklarla çalışacak bir programlama yapılabilir mi?" Bir süre kafa yorduktan sonra bu işlemi Thread mantığı ile çözebileceğimiz kanaatine vararak, kodlama için çalışmalara başladık. Aslında bu konuda, internette fazla türkçe kaynak bulunmuyor ama deneyerek ortaya birşeyler çıkarabilirsiniz. Ama biz size biraz yardımcı olalım.
Bu ne işe yarayacak? Daha önceden yazılmış olan bu makalede çok fazla kayıt bulunduran bir veritabanından gelen bilgiler doğrultusunda e-mail gönderilmesi işlenmiş. Biz konuyu biraz daha farklı yoldan ele alıp, işlemi sonsuz bir döngüye sokarak, belirli aralıklarla veritabanından veri kontrolü yapıp duruma göre müdahale edilmesi konusunda karar kıldık. Aslında belirttiğimiz yöntem için normal bir sunucu kiralanıp, sunucu üzerinde normal bir programla bu işlemi gerçekleştirebilirsiniz. Ama hem maliyet bakımından hem de bir nebze proje bütünlüğü için bu yöntem biraz daha uygun görünüyor.
Asp.Net ile gelen Thread desteği bizim bu amacımıza yardımcı olacak. Basit olarak Thread’ler, bir programın paralel ve birbirinden bağımsız işlemler yapmasını sağlayan işlem parçacığıdır diyebiliriz. Bu şekilde çalışma yeteneği sayesinde bizim amacımıza uygunluk göstermektedir. Konuyu fazla uzatmadan örnek kodlamalarımızı incelemeye başlayalım.
Global.asax
<%@ Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
GenelIslemler Islemim = new GenelIslemler();
Islemim.SurekliIslemleriBaslat();
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
}
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
</script>
Bu projeyi Windows üzerinde Asp.Net ile gerçekleştireceğiz ve Global.asax bizim ilk tetikleyicimiz olacak. Global.asax'ın prosedürlerinden biri olan void Application_Start(object sender, EventArgs e) ile web sayfamızın çalıştığı anda Thread işlem parçacığımızı başlatıyoruz. Burada da görüldüğü üzere GenelIslemler diye bir sınıf tanımlaması yapıp, thread'ımızı buradan çalıştırıyoruz.
GenelIslemler.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Threading;
using System.Data;
/// <summary>
/// Summary description for GenelIslemler
/// </summary>
///
public class GenelIslemler
{
static int sayac = 0;
public void SurekliIslemleriBaslat()
{
Thread Calistir = new Thread(new ThreadStart(DegerArttir));
Calistir.IsBackground = true;
Calistir.Start();
}
public void DegerArttir()
{
do
{
sayac++;
System.Threading.Thread.Sleep(1000);
} while (sayac != -1);
}
public string DegerAl(Page sayfa)
{
return sayac.ToString();
}
}
Aslında burada görülen DegerArttir() prosedürü bizim ana kodlamamız. Dikkat edildiği üzere sonsuz bir döngü içermekte. Normalde bu şekilde çalıştığında, sayaç değeri sürekli arttırılacağı için kodlama cevap vermeyip, sayfa açılışı uzayacak ve muhtemelen en son olarak bağlantı zaman aşımına uğrayıp, sayfa ile bağlantı kesilecektir. Bunun önüne geçmek için SurekliIslemleriBaslat() prosedürü içerisinde bir thread tanımlayıp, thread in çalıştıracağı prosedür olarak DegerArttir() 'ı belirtiyoruz. İşlemimizin arka planda çalışmasını ve sayfalarımızı etkilememesi için thread in background özelliğini aktif hale getiriyoruz. DegerArttir() prosedürü içerisinde belirtilen System.Threading.Thread.Sleep(1000); kodu ile işlemin 1 saniyelik duraksamasını istiyoruz. Prosedürümüz zaten sonsuz döngü içinde olduğu için bu duraksama ile sanki saniyede bir çalışan bir prosedür halini almakta.
Buraya kadar işlemleri tamamladıktan sonra sonsuza kadar devam eden ve web sayfamızı etkilemeyen bir işlemimiz oldu. DegerArttir() prosedürü içerisinden başka prosedürler çağırarak veritabanımızı kontrol ettirebilir yada DegerArttir() 'dan faklı prosedürler yazabiliriz.
Kodlamanın çalışıp, çalışmadığını incelemek için DegerAl() fonksiyonunu tanımladık ve aşağıda belirtilen kodlamalar ile deneme yaptık. Sonuç : pozitif.
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
<br />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Sayaç Değeri Getir" />
</div>
</form>
</body>
</html>
Default.asp.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
GenelIslemler Islemim = new GenelIslemler();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Şu anki sayaç değeri : " + Islemim.DegerAl(this);
}
}
Projenin hazır kodlamasını buradan indirebilirsiniz. Anlatım biraz karmaşık oldu ama artık kusura bakmayın. Güzel çalışmalarda kullanmanız dileği ile...