A Brief Introduction to Multi-threading in C# (Part2:Manage Threads Manually)

From the previous post, Part1:CLR-Managed Thread, what if you want absolute control over the execution of the threads. Here are the ways:

- Thread Monitor

Concurrent executions of threads, which's called race conditions, can bring the whole application down due to the inconsistency of the application state or variable. Monitor can guarantee thread safe. It means that , it will ensure that your code's executed in a synchronized fashion. Monitor.Enter and Monitor.Exit define a critical section for your code. Example:

 

public class Task
        {
            public string TaskName { get; set; }
            public Task(string taskName)
            {
                TaskName = taskName;
            }
            public bool Commit()
            {
                Console.WriteLine("Task : " + TaskName + " was done!");
                return true;
            }
        }
        public class Robot
        {
            //initialize taskList as a thread-safe queue.
            private Queue _TaskList = Queue.Synchronized(new Queue());
            public string Name { get; set; }

            public void AddTask(Task task)
            {
                _TaskList.Enqueue(task);
            }
            public void PerformTaskList(object syncObj)
            {
                //lock task list, so other robots cannot perform the same list.
                Monitor.Enter(syncObj);
                //suppose:  2 sec initialize then commit task list.Thread.Sleep(2000);
                Console.WriteLine("ROBOT '" + Name+"' is executing... ["+DateTime.Now.TimeOfDay+"]");
                Thread.Sleep(2000);
                foreach (Task task in _TaskList) task.Commit();
                Console.WriteLine("ROBOT '" + Name + "' finishes executing... ["+DateTime.Now.TimeOfDay+"]\n");
                Monitor.Exit(syncObj);
            }
        }
static void Main(string[] args)
        {
            Robot robo1 = new Robot() { Name = "Steven" };
            Robot robo2 = new Robot() { Name = "Bill" };
            Task task1 = new Task("Clean the room");
            Task task2 = new Task("Cook a meal");
            robo1.AddTask(task1);
            robo1.AddTask(task2);
            robo2.AddTask(task1);
            robo2.AddTask(task2);
            object syncObj = new object();
            ThreadPool.QueueUserWorkItem(new WaitCallback(robo1.PerformTaskList), syncObj);
            ThreadPool.QueueUserWorkItem(new WaitCallback(robo2.PerformTaskList), syncObj);

            Console.ReadLine();
        }

Robo2'll wait for robo1 to finish its execution (syncObj'll do sycn lock for us). The shortcut of Monitor.Enter(obj) and Monitor.Exit(obj) is lock(obj){ ... }. Try it by yourself!

 

- Interthread Signaling 

Imagine that 2 robots working together, robo1 receives task on the carousal and notifies robo2 to process that task. The second task comes in, the process of receiving and processing are still the same cycle by cycle. Carousal is like a pipeline event that enables robots working together. So, robo1 must signal robo2 to do its job. I'll show how robots complete their common tasks by using the notification ManualResetEvent and AutoResetEvent (both of them derived from EventWaitHandle which in turn derived from WaitHandle as introduced in Part1) (Note that some parts of code are modified for the demonstration): 

public class Robot
    {
        //worker thread to process the task assigned for this robot.
        protected Thread processingThread;
        //initialize taskList as a thread-safe queue.
        public Queue TaskList { get; set; }

        public string Name { get; set; }
        public ManualResetEvent NotificationEvent { get; set; }
    }
public class ReceiverRobot : Robot
    {
        //this part is processed on the application's thread.
        public void ReceiveTask(Task task)
        {
            TaskList.Enqueue(task);
            //send signal to processingThread that's waiting that the task's come in.
            NotificationEvent.Set();
        }
    }
    public class ProcesserRobot : Robot
    {
        public ProcesserRobot()
        {
            //create and start a new worker thread.
            processingThread = new Thread(new ThreadStart(PerformCommonTaskList));
            processingThread.Start();
        }
        //this method's processed on a worker thread.
        public void PerformCommonTaskList()
        {
            while (true)
            {
                //wait the receiver robot to assign the task.
                NotificationEvent.WaitOne();
                //reset the signal back to nonsignal state.
                //for AutoResetEvent you don't need this line; it'll reset automatically after event's signaled(set)
                NotificationEvent.Reset();
                while (TaskList.Count > 0) ((Task)TaskList.Dequeue()).Commit();
            }
        }
    }

        static void Main(string[] args)
        {
            //create a single pipeline event used for intercommunicating (false - initially set to nonsignal state).
            ManualResetEvent pipelineEvent = new ManualResetEvent(false);
            //create shared taskList.
            Queue taskList = Queue.Synchronized(new Queue());

            ReceiverRobot robo1 = new ReceiverRobot();
            robo1.NotificationEvent = pipelineEvent;
            robo1.TaskList = taskList;
            ProcesserRobot robo2 = new ProcesserRobot();
            robo2.NotificationEvent = pipelineEvent;
            robo2.TaskList = taskList;

            Task task1 = new Task("Clean the room");
            Task task2 = new Task("Cook a meal");
            robo1.ReceiveTask(task1);
            robo1.ReceiveTask(task2);

            Console.ReadLine();
        }

Not only applicable to this 2 robot, but imagine this as a bunch of pipeline workers. So far, I'll have to let you develop further thought for you own interthread communication.

That's enough for today. Stay tuned for the next part... : - )

kick it on DotNetKicks.com  Shout it

Categories:   .NET ASP.NET C# | Tip(s)
Actions:   E-mail | del.icio.us | Permalink | Comments (3) | RSS


A Brief Introduction to Multi-threading in C# (Part:Automatic Threads)

Hello again, today post is a brief intro of multi-threading that i read from a book (http://www.amazon.com/Practical-Financial-Markets-Experts-Voice/dp/1590595645) and summarize it here. If you want to do multithreading there're a plenty of ways:

- Thread Pools: the most easiest because it's auto-managed by CLR already, you just tell them what task you want them to process and thada!. The pool also knows how to utilize the CPU. If its tasks're full-loaded, the pool won't create anymore threads. There're 2 kinds of thread in Thread Pools 1) worker threads 2) I/O threads(e.g. reading data from I/O, Socket, or Network). The default settings'd be 25 worker, 25 I/O threads. If there's no available thread to process a new task, it'll queue that task for a while. For the sample code:

 

public class Task
        {
            public string TaskName { get; set; }
            public Task(string taskName)
            {
                TaskName = taskName;
            }
            public bool Commit()
            {
                Console.WriteLine("Task : " + TaskName + " was done!");
                return true;
            }
        }

        static void Main(string[] args)
        {
            //param1: callback method, param2: callback method's parameters
            ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTask), new Task("Clean the house"));
            ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTask), new Task("Do breakfast for me"));
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTask), new Task("Drive me a car"));
Console.ReadLine(); } public static void ProcessTask(object task) { ((Task)task).Commit(); }

 

No need to explain, pretty simple and easy. Note that the callback method must be static method.

- Asynchronous Delegate Method: as the title suggested, I will use Delegate to enable async method call.  The behind the scene of BeginInvoke and EndInvoke use ThreadPools to gain CPU utilization as well: 

public class Task
        {
            public string TaskName { get; set; }
            public Task(string taskName)
            {
                TaskName = taskName;
            }
            public bool DoWork()
            {
                Console.WriteLine("Task : " + TaskName + " was done!");
                return true;
            }
        }
        public class TaskStatus
        {
            public TaskStatus(string taskName,bool isCompleted)
            {
                TaskName = taskName;
                IsCompleted = isCompleted;
            }
            public string TaskName{get;set;}
            public bool IsCompleted { get; set; }
        }

        public delegate TaskStatus TaskHandler(Task task);

        static void Main(string[] args)
        {
            //assign ProcessTask method to TaskHandler delegate (their signatures must be matched!)
            TaskHandler processTaskHandler = new TaskHandler(ProcessTask);
            //begine async method call
            IAsyncResult result = processTaskHandler.BeginInvoke(new Task("Clean the house"), null, null);
            //Ok! stay here (block the current thread) until ProcessTask's completed (wait not more than 2 sec).
            result.AsyncWaitHandle.WaitOne(2000);
            //get the result from the operation (ProcessTask).
            TaskStatus status = processTaskHandler.EndInvoke(result);

            Console.WriteLine(status.TaskName + ((status.IsCompleted)?" is completed.":" is failed."));

            Console.ReadLine();
        }

        public static TaskStatus ProcessTask(object t)
        {
            Task task = (Task)t;
            TaskStatus status = new TaskStatus(task.TaskName, task.DoWork());
            return status;
        }

Using this may troublesome cause you have to if the status of operation is already completed by using WaitHandler. Alternatively, you can assign notification callback method to BeginInvoke as well. When complete BeginInvoke, it'll execute notification callback and now you don't need to handle WaitHandler anymore.

//others're the same as in the section above.
static void Main(string[] args)
        {
            //assign ProcessTask method to TaskHandler delegate (their signatures must be matched!)
            TaskHandler processTaskHandler = new TaskHandler(ProcessTask);
            AsyncCallback processTaskCompleted = new AsyncCallback(ProcessTaskCompleted);
            //begin async method call, also pass notification callback and ProcessTask handler.
            IAsyncResult result = processTaskHandler.BeginInvoke(new Task("Clean the house"), processTaskCompleted, processTaskHandler);

            Console.ReadLine();
        }

public static void ProcessTaskCompleted(IAsyncResult result)
        {
            //get the delegate object after the async call's invoked.
            TaskHandler processTaskHandler = (TaskHandler)((System.Runtime.Remoting.Messaging.AsyncResult)result).AsyncDelegate;
            //get the result from the operation (ProcessTask).
            TaskStatus status = processTaskHandler.EndInvoke(result);
            Console.WriteLine(status.TaskName + ((status.IsCompleted) ? " is completed." : " is failed."));
        }
Hope this help. Stay tuned for the next part...

Categories:   .NET ASP.NET C# | Tip(s)
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | RSS


Rename and Trim MP3 Tag

Have you ever download file from internet which has many wrong tag name and some annoying number on them? Well, I have a small solution for your problem. This is a small program i wrote to overcome that problem. It'll trim the first prefix letters and delete the wrong MP3 Tag from your mp3

What you need is a library called TagLib from http://developer.novell.com/wiki/index.php/TagLib_Sharp, a library allows you to modify id3 tag, download it and put it on your bin folder.

1. I put a code to be invoked on button click event

 

private void button1_Click(object sender, EventArgs e)
  {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.ShowDialog();
            if (dialog.SelectedPath != "")
            {
                // I read number From textbox to get number of characters to be trim
                int numOfPrefix = Int32.Parse(textBox1.Text);
            }
  }

 

2. I read file names from the folder i've selected. Then I substring the folder path + number of the letters i want to remove.

 

String[] x = Directory.GetFiles(dialog.SelectedPath);
                char[] charset = dialog.SelectedPath.ToCharArray();
                List theFileSet = new List();
                foreach (String a in x)
                {
                    String thechar = a;
                    // Num of prefix is number of letter i want to remove
                    thechar = thechar.Substring(charset.Length + 1 + numOfPrefix);
                    
                    // Add it to list
                    theFileSet.Add(dialog.SelectedPath + "\\" + thechar);
                }

                // x array is the original file names, y array is the modified file names
                String[] y = theFileSet.ToArray();

 

3. I use move operation to rename the filename, and i modifile id3 tag by using tagLib library (don't forget to add the reference)

for (int i = 0; i < x.Length; i++)
                {       
                    // Rename filename by Move operation
                    System.IO.File.Move(x[i], y[i]);

                    // Begin Tag modification
                    TagLib.File f = TagLib.File.Create(x[i]);

                    // I remove album artists, album, genres and composers
                    f.Tag.AlbumArtists = null;
                    f.Tag.Album = "";
                    f.Tag.Genres = null;
                    f.Tag.Composers = null;

                    // Don't forget to save the file Tag
                    f.Save();
                }

Ok that's all the operation in this program. I'll post the full code in my personal blog, don't forget to check out my personal blog. I put what i learn on my blog http://cmmadnat.posterous.com/mp3-renamer-and-id3-tag-editor Thank you, see ya!

Categories:   .NET ASP.NET C#
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | RSS


Print Stack Trace of Exceptions

You can notice many changes in this blog. Hope you like this new look and feel. If you have some ideas or complaints, leave the message below. We'll fix that. :)

My story today is about exception stack trace. How we gonna make use of inner exception. For example, I call obj1, then obj1 calls obj2. If error occurs in obj2, obj2 throws its error which has the type Obj2Exception. This error also defects obj1, so obj1'll throw Obj1Exception as well. In conclusion, obj2 throws Obj2Exception and obj1 throws Obj1Exception respectively.

We need to know the stack trace of calling those exceptions but how? How about using Exception.StackTrace in the catch(..) block? In that case, you'll get the result like:

 

at ExceptionTest.Program.MockObject.DoOuterTask() in C:\Documents and Setting
s\winladen\My Documents\Visual Studio 2008\Projects\ConsoleApplication1\Exceptio
nTest\Program.cs:line 35
   at ExceptionTest.Program.Main(String[] args) in C:\Documents and Settings\win
laden\My Documents\Visual Studio 2008\Projects\ConsoleApplication1\ExceptionTest
\Program.cs:line 44

 

Which I don't need. Instead, using innerException 'd be more concise. I'll show you this example. Suppose I have this class:

class MockObject
        {
            public void DoInnerTask()
            {
                throw new MyInnerException("error: DoInnerTask()");
            }
            public void DoTask()
            {
                try
                {
                    DoInnerTask();
                }
                catch (Exception e)
                {
                    throw new MyException("error: DoTask()", e);
                }
            }
            public void DoOuterTask()
            {
                try
                {
                    DoTask();
                }
                catch (Exception e)
                {
                    throw new MyOuterException("error: DoOuterTask()", e);
                }
            }
        }

The method's called like in a stack fashion, as you see.

 

public class MyInnerException : Exception
    {
        public MyInnerException(string message) : base(message) { }
        public MyInnerException(string message, Exception innerEx) : base(message, innerEx) { }
    } 
    public class MyException:Exception{
        public MyException(string message) : base(message) { }
        public MyException(string message, Exception innerEx) : base(message, innerEx) { }
    }
    public class MyOuterException : Exception
    {
        public MyOuterException(string message) : base(message) { }
        public MyOuterException(string message, Exception innerEx) : base(message, innerEx) { }
    }

 

Ok, the point in this story's here, we make use of iteration of innerException in the catch(..) block:

static void Main(string[] args)
        {
            try
            {
                MockObject obj1 = new MockObject();
                obj1.DoOuterTask();
            }
            catch (Exception e)
            {
                for (Exception e1 = e; e1 != null; e1 = e1.InnerException)
                {
                    Console.WriteLine("Error type: "+e1.GetType());
                }
            }
        }

 

The result:

 

Error type: ExceptionTest.MyOuterException
Error type: ExceptionTest.MyException
Error type: ExceptionTest.MyInnerException

 

We print the types of exceptions thrown; fill in the detail you need for the stack trace by yourself.

Hope this help!

Shout it    kick it on DotNetKicks.com

Categories:   .NET ASP.NET C# | Tip(s)
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | RSS


Twitter API With OAuth (Automatic Post your tweet system)

Hi There. It's been a long time since my Last post. You didn't forget about me, is that right?

Many of you've been asking me about my lastest project (ICTbookplus). My Twitter Feature
which will post tweet by your account on twitter.com saying that the user has bought a book
from my website (wicked marketing, right?). Try It! (sign in with twitter for full detail!).

Summary of what you need to do!

 

  1. Use your twitter account to  add new Application to the twitter pool.
  2. Download Twitter oAuth example from here
    (Credit http://apiwiki.twitter.com/http://www.voiceoftech.com/swhitley/?p=681)
  3. Coding!
Sounds easy! Let's begin
  1. On your twitter account home, follow these steps.

  2. Fill in your website information (Real internet Url on Callback URL)

  3. Now Remember your consumer key and Consumer secret
  4. Now, use  oAuth from example above to program here

  5. Include two file in your Project (oAuth.cs and oAuthTwitter.cs)
  6. Code your call back page like this

    1.         protected void Page_Load(object sender, EventArgs e)
    2.         {
    3.             string url = "";
    4.             string xml = "";
    5.             oAuthTwitter oAuth = new oAuthTwitter();
    6.  
    7.             if (Request["oauth_token"] == null)
    8.             {
    9.                 //Redirect the user to Twitter for authorization.
    10.                 //Using oauth_callback for local testing.
    11.                 Response.Redirect(oAuth.AuthorizationLinkGet() + "&oauth_callback=");
    12.             }
    13.             else
    14.             {
    15.                 //Get the access token and secret.
    16.                 oAuth.AccessTokenGet(Request["oauth_token"]);
    17.                 if (oAuth.TokenSecret.Length > 0)
    18.                 {
    19.                     //We now have the credentials, so make a call to the Twitter API.
    20.                     url = "http://twitter.com/account/verify_credentials.xml";
    21.                     xml = oAuth.oAuthWebRequest(oAuthTwitter.Method.GET, url, String.Empty);
    22.                     //apiResponse.InnerHtml = Server.HtmlEncode(xml);
    23.                    
    24.                     XElement x = XElement.Parse(xml);
    25.  
    26.                     //POST Test
    27.                     url = "http://twitter.com/statuses/update.xml";
    28.                     xml = oAuth.oAuthWebRequest(oAuthTwitter.Method.POST, url, "status=" + oAuth.UrlEncode("I've just bought TextBook From ICTBook+ at http://cmmadnat.theblogfor.net/user"));
    29.                     //apiResponse.InnerHtml = Server.HtmlEncode(xml);
    30.                  }
    31.               }
    32.         }

This page will simply encode your request with your Consumer Key and Consumer secret, send
it to twitter for user authentication. Then it retrieve token (in XElement x) which contains user
identity.

On the post test, our code uses token to post status to twitter website.

7. Configure web.config, insert your website Consumer key and secret key.

  <appSettings>
    <add key="consumerKey" value="fuBAODgxjpS16FNSskUw" />
    <add key="consumerSecret" value="4CECc7JaclVtmXTzRmdZXUZpiegdUXqRP42cRE"/>
  </appSettings>

8. upload your page to website specific in your twitter application. ! Yeah

Thank you !!!

Categories:   .NET ASP.NET C# | Tip(s)
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | RSS


 

Tag Cloud