Skip to main content

Using BackgroundWorker in C#

අපි අද කතා කරන්න හදන්නේ තවත් අපිට ගොඩක් ප්‍රයෝජනවත් වෙන C# වල තියෙන feature එකක් ගැන. ඒ තමා මේ BackgroundWorker කියන component එක, මේක පාවිච්චි කරලා අපිට පුළුවන් අපේ programs වලට Threads හදාගන්න. අපි සාමාන්‍යයෙන් Threads පාවිච්චි කරන්නේ මොකක් හරි ගොඩක් වෙලා යන වැඩක් program එකෙන් කරද්දී ඒ වැඩේ program එක පාවිච්චි කරන කෙනාට එහෙම නැත්නම් User ට නොතේරෙන විදියට කරගන්න, උදාහරණයක් විදියට අපි database එකකට connect වෙලා data set එකක් fetch කරනවා කියල හිතන්න මේ වැඩේට ලොකු වෙලාවක් යනවා නම් User හිතෙන්නේ program එක හිර වෙලා කියල. ඉතින් මෙන්න මේ ප්‍රශ්නේ විසඳා ගන්න පුළුවන් අපිට BackgroundWorker එක පාවිච්චි කරලා. ඒ කියන්නේ පොඩි Progress Bar එකක් වගේ දෙයක් පෙන්නලා user ට කියන්න පුළුවන් වැඩේ ඇතුලෙන් කෙරෙනවා කියලා.

හරි අපි පටන් ගමු, මුලින්ම කරන්න තියෙන්නේ Visual Studio වලින් Windows Forms Application එකක් හදාගන්න එක. ඊට පස්සේ සාමාන්‍යයෙන් ඔයාලගේ right hand side එකේ Tool Box එක දිහා බැලුවම පෙනෙයි මෙන්න මේ වගේ


මෙතන අපිට පේනවා BackgroundWorker කියල tool එකක් තියෙනවා, දැන් මේක drag කරලා drop කරන්න අපේ form එකට. ඊට පස්සේ මම එක rename කරගත්ත bgWorker කියල. දැන් අපි පොඩ්ඩක් බලමු මේකේ තියෙන Events මොනවද කියල.


අපේ BackgroundWorker component එකේ Events 3 ක් තියෙනවා,
  1. DoWork - මේ event එක ඇතුලට තමා අපි අපේ time consuming operation එක දාගන්න ඕනෙ
  2. ProgressChanged - අපේ Thread එකේ progress එක user ට පෙන්නන්න ඕනෙ නම් අපිට මේ event එක පාවිච්චි කරන්න පුළුවන් 
  3. RunWorkerCompleted - මේ event එක fire වෙන්නේ Thread එකෙන් කරන්න දීල තියෙන වැඩේ ඉවර උනාම.
අපි මේ events 3 ම පාවිච්චි වෙන විදිහ වෙන වෙනම විස්තර ඇතුව බලමු.

පහල තියෙන code එක තමයි අපි පාවිච්චි කරලා තියෙන්නේ.

 using System;  
 using System.ComponentModel;  
 using System.Windows.Forms;
  
 namespace BgWorkerSample  
 {  
   public partial class BgWorkerDemo : Form  
   {  
     public BgWorkerDemo()  
     {  
       InitializeComponent();  
     }  
     private void bgWorker_DoWork(object sender, DoWorkEventArgs e)  
     {  
       System.Threading.Thread.Sleep(3000);  
     }  
     private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
     {  
       MessageBox.Show("Thread Completed");  
     }  
     private void btnInvoke_Click(object sender, EventArgs e)  
     {  
       bgWorker.RunWorkerAsync();  
     }  
   }  
 }  

දැන් මේ BgWorker_DoWork කියන්නේ DoWork event එකේ handler එක. මේක ඇතුලේ අපි දාල තියෙනවා පොඩි delay එකක්. Thread.Sleep() කියන method එකට 3000 pass කලාම එකෙන් කියවෙන්නේ  ඒ Thread එක මිලි තත්පර 3000 ක් එහෙමත් නැත්නම් තත්පර 3 ක් sleep වෙනවා කියන එක. 

ඊට පස්සේ bgWorker_RunWorkerCompleted event handler එක තියෙනවා, මේක තමා Background worker එකෙන් කරන වැඩේ කරලා ඉවර උනාම call වෙන method එක. මේකේ අපි ලියල තියෙනවා "Thread Completed" කියල message box එකක් පෙන්නන්න කියලා.

අපි Thread එක start කරන්න use කරන button එකේ click event අනික් එක. එතන අපි bgWorker එකේ RunWorkerAsync() කියන method එකට call කරලා තියෙනවා. 

මේ code එක run කරලා බැලුවම ඔයාලට පෙනෙයි Button එක click කරලා හරියටම තත්පර 3 න් message box එක එනවා. ඒ එක්කම ඒ තත්පර 3 ඇතුලත අපේ Form එක freeze වෙන්නෙත් නෑ. UI එක freeze වෙලාද නැද්ද කියන හොයාගන්න පුළුවන් Form එකේ Maximize Minimize වගේ buttons click කරලා බලන්න. 

දැන් ඔයාලට පුළුවන් මෙහෙම දෙයක් කරන්න,

 private void btnInvoke_Click(object sender, EventArgs e)  
 {  
   //bgWorker.RunWorkerAsync();  
   System.Threading.Thread.Sleep(3000);  
   MessageBox.Show("Thread Completed");  
 }  

මේ code එක run කලාම වෙන්නෙත් ඉස්සෙල්ල වෙච්ච දේම තමා ඒත් ඔයාලට පෙනෙයි තත්පර 3 ක් යනකන් UI එක freeze වෙනවා කියන එක.

ඉතින් දැන් ඔයාලට පැහැදිලි ඇති ඇයි අපි BackgroundWorker එකක් පාවිච්චි කරන්නේ කියන එකයි කොහොමද අපේ program එකට BackgroundWorker එකක් add කරගන්නේ කියන එකයි.

අපි දැන් පොඩ්ඩක් බලමු මේ Thread එකත් එක්ක අපේ main program එක කොහොමද communicate කරන්නේ කියල. RunWorkerAsync කියන method එක බැලුවම පේනවා එකේ තවත් Overload එකක් තියෙනවා කියල. අපිට පුළුවන් ඒ overload method එකට pass කරන්න object type එකේ parameter එකක්. ඔයාල දන්නවනේ object එකක් යවන්න පුළුවන් කියන්නේ අපිට ඒකට ඕනෙම class එකකින් හදාගන්න object එකක් යවන්න පුළුවන් කියල.

එතකොට අපි බැලුවොත් DoWork() method එක, එකේ තියෙනවා DoWorkEventArgs කියල parameter එකක්. 
  1. e.Argument - මේකට තමා අපි ඉස්සෙල්ල දැක්ක RunWorkerAsync method එකෙන් එන argument කියන parameter එක එන්නේ. 
  2. e.Result - අපිට පුළුවන් මේ thread එක ඇතුලේ කරපු process එකේ result එකක් තියෙනවා නම් ඒක මේ property එක හරහා ආපහු main program ඒකට එහෙමත් නැත්නම් RunWorkerCompleted method ඒකට යවන්න.
  3. e.Cancel - මේක අපි පාවිච්චි කරන්නේ අපේ background operation එක හරියට වැඩ කලාද කියල main program ඒකට කියන්න.
අපි දැන් පොඩ්ඩක් බලමු මේ program එක තව ටිකක් improve කරගන්නේ කොහොමද කියල. Progress Bar එකක් දාල user ට අපේ background job එකේ progress එක පෙන්නන්න තමා අපි දැන් ලෑස්ති වෙන්නේ.

දැන් Toolbox එකෙන් අරන් අපේ form එකට ProgressBar control එකක් දාගන්න. එකේ size එක position එක එහෙම හොඳ විදිහට හදාගන්න. ඊට පස්සේ අපේ BackgroundWorker එකේ තියෙන WorkerReportsProgress කියන property එක True කරගන්න ඕනෙ. දැන් අපේ DoWork method එක මෙන්න මේ පහල පෙන්නලා තියෙන විදිහට වෙනස් කරගන්න.


     private void bgWorker_DoWork(object sender, DoWorkEventArgs e)  
     {  
       for (int i = 0; i < 10; i++)  
       {  
         System.Threading.Thread.Sleep(1000);// Actual time consuming operation  
         bgWorker.ReportProgress(10);  
       }  
     }  


පහල තියෙන්නේ අපේ program එක run වෙනකොට පෙනෙන විදිහ.


Comments

Popular posts from this blog

Adding Unique Constraints with Entity Framework Code First

Entity Framework Code First is a great way to define and maintain your database within your application it self. While it poses a nice set of complementing libraries like Data Annotations and Fluent Configurations which helps you specially in defining phase of your database, it would give you a headache if you try to define a unique constraint on a column. For example in the users table of your application you could probably have an int ID column which would serve as the primary key and you might need to make your Username column a unique one. Since you are using EF Code First you will soon find out there is no direct way to accomplish this requirement. Unfortunately fluent configurations doesn't have syntax like HasUnique(u => u.Username); I asked the same question in stackoverflow , but didn't get a convincing answer. Since there is no direct support from EF for this you could take one of following alternatives to achieve it. Approach 1 :  

How to disable ASP.NET page validations

ASP.NET වල page validation පාවිච්චි වෙන්නේ script injection attacks නවත්ත ගන්න, ඒ ගැන වැඩි විස්තර ඕනෙ නම් මෙතනින් බලාගන්න පුළුවන්. හැබැයි මේක අපිට කරදරයක් වෙන වෙලාවලුත් තියෙනවා. උදාහරණයක් විදියට අපි හිතුවොත් අපි අපේ user ට හිතලම ඉඩ දෙන්න ඕනේ script වගේ දේවල් page එකකට submit කරන්න. මේක උනේ මම වැඩ කරපු Admin site එකක, මේ site ඒක run වෙන්නේ company එකක intranet එකේ, මේක පාවිච්චි කරන්නේ Admin ල විතරයි ඒක අපි වෙන විදියකට authenticate කරනවා ඒ ගැන පස්සේ කියන්නම්. ඉතින් ප්‍රශ්නේ උනේ මේ page validations නිසා අපිට ඕනේ කරන user inputs ගන්න විදියක් නැති උනා. ඒක විසඳගන්න මට සිද්ද උනා page validations disable කරන්න. ඒක කරන්න ක්‍රම දෙකක් තියෙනවා. මොන දේ කරන්නත් ඉස්සෙල්ල site එකේ web.config එක පහල තියෙන විදිහට වෙනස් කරන්න ඕනේ. (සැ. යු. ASP.NET 4.0 web sites සඳහා). <configuration> <system.web> <httpRuntime requestValidationMode="2.0"/> </system.web> </configuration> ඊට පස්සේ පහල තියෙන ක්‍රම දෙකෙන් එකකට වැඩේ කරන්න පුළුවන්. Site එක

HTML INPUT enhancement with Regular Expressions and Java Scripts

අද කථා කරන්න යන්නේ බොහොම සරල දෙයක් ගැන. සරල උනාට ඉතින් මට මේක කරගන්න ඕන වෙලා හොයන කොට නම් ඉතින් හොයාගන්න ටිකක් කරදර උනා, ඒ නිසාම තමා මම හිතුවේ මේක ගැන ලියන්න ඕනෙ කියල. අපි හැමෝම HTML forms validate කරන්න Java Script පාවිච්චි කරනවා නේ, එක අලුත් දෙයක් නෙමේ. ඒ වගේම තමා Regular Expressions කියන්නෙත් අපිට අලුත් දෙයක් නෙමේ. අපි බලමු මේ දෙකම පාවිච්චි කරලා HTML textbox එකකට අපිට ඕනෙ characters විතරක් enter කරන්න දෙන්නේ කොහොමද කියල. මෙන්න මේක තමා අපි පාවිච්චි කරන HTML page එක. <!DOCTYPE html> <html> <head> <title>JS and RegEx</title> </head> <body> <label for="txtUsername">Username</lable> <input type="text" id="txtUsername" placeholder="Enter Username"/> </body> </html> මේ තියෙන page එක html විදිහට save කරලා browser එකේ බැලුවම මෙන්න මේ වගේ තමා පෙන්නේ. දැන් හිතන්න අපිට මේ username එකට @,#,%,$ වගේ