Friday, July 12, 2013

Interthread Communication with C# in the .NET Framework

Abstract

In this article I explain how a resource intensive job is sourced out to its own thread. Furthermore I will discuss how to stay in communication with that thread. The article is for a Windows Forms application using C# in the .NET framework.
I will not talk about the theoretical concept of threading or event handling. It is assumed that you either know this or know where to learn about. (Or don’t know and even don’t want to know but simply make your application run.)
A source file is provided that contains a class with some templates for easy interthread communication.

Multithreading

In many applications one would like to carry out a computation in the background. I.e. the user interface shouldn’t “freeze” while the computation is running. Assume for example, a user started the evaluation by accident. He won’t be very pleased having to wait several minutes (or even longer) until he can correct his mistake.
The solution is to run the computation in its own thread. This is really easy:
private void button_Click(object sender, EventArgs e)
{
    private Thread kernel_thread;
    kernel_thread = new Thread(compute);
    kernel_thread.Start();
}

private void compute()
{
    // Here a complex job is carried out.
}

In this example, the method compute() will run in its own thread named kernel_thread. Note that compute() must be void and mustn’t take any arguments. Don’t forget to add
using System.Threading;
at the Begin of the code. If the user wants to abort the computation, the following would be a rough but effective way to do so:
private void kill_kernel()
{
    if (kernel_thread != null)
    {
        kernel_thread.Abort();
    }
}

I think there are better ways to achieve this since any intermediate results will probably be lost. However, for the case I had to solve this was an appropriate choice.

Event Handling

Everything is cute and dandy but yet the user doesn’t know what the “kernel” is doing. In fact, we would like to be able to communicate with it. Communication is a vast field but the very least we would like to do is enabling the kernel to print some status information. Writing a console application one could simply use
print("I'll be finished soon!");
replacing print by whatever command is appropriate for the chosen language.
For my Windows Forms application I have created a form with a text box that will accept the kernel output. Therefore the class has a method
public void log_print(string text)
{
    text_box.AppendText(text);
    text_box.AppendText(Environment.NewLine);
}

that takes a string and adds it to the text box. But this method can’t be called from the kernel. Event handlers are the solution of choice. As announced, I won’t explain the concept of event handling but simply give the solution.
Let’s go to the class that wants to write something to the text box. We want to have something like a notify() method. Do get it, we first have to declare a delegate that will be invoked at the event. This handler must be void and take an object and an instance of the EventArgs class as argument. However, if we want to have it more customized, we can declare our own class that is derived from the EventArgs class. In our case, we want to send a string so we define
public class EventArgsNotification : EventArgs
{
    public string info_text; // The text we want to send.
}

Now we can declare our delegate
public delegate void EventHandlerNotification(object sender, EventArgsNotification e);
and an event
public static event EventHandlerNotification EventNotification;
Now we could fire this event using
EventArgsNotification e = new EventArgsNotification();
e.info_text = message;
EventNotification(this, e);

But not only that this are three lines of code for what we wanted to have a simple function it, even worse, also makes our application crash! The first problem can be solved by defining a method that does the job of declaring the event arguments an firing the event. The second problem is because the event is fired but nobody cares about. We should check this before we fire it. Here is the handy method:
private void notify(string message)
{
    if (EventNotification != null)
    {
        EventArgsNotification e = new EventArgsNotification();
        e.info_text = message;
        EventNotification(this, e);
    }
}

Subscribing to the Event

Now we have defined an event and can use it. But if it is fired, no one cares. In fact, it isn’t even fired because we check it for not being null. An event is something like a list of functions subscribing to it. So next we have to go to our class that contains the text box and add the following:
// Method that should be called if an event is fired:
private void receive_notification(object sender, EventArgsNotification e)
{
    log_print(e.info_text);
}

// Subscribe:
kernel.EventNotification += receive_notification;

Now we’ve subscribed a method to the event that will be called as it is fired. Whops, that doesn’t work! This is because as the method is subscribed to the event in the kernel class, it is also called from the thread the kernel runs on. This is not the thread the text box is managed on. Fortunately, the .NET framework provides us a good workaround. We rewrite thereceive_notification method as follows:
private void receive_notification(object sender, EventArgsNotification e)
{
    if (InvokeRequired)
    {
        Invoke(new EventHandlerNotification(receive_notification), new object[] { sender, e });
    }
    else
    {
        log_print(e.info_text);
    }
}

InvokeRequired is true if the event is fired from a different thread. In this case, the above method will simply fire the event again from it’s own thread. (That’s what Invoke does.) This tools are provided in the ComponentModel so we add at the beginning
using System.ComponentModel;
That’s it!

Making Everything more Comfortable

Maybe we have a lot of classes that want to be able to notify the user. Doing all the stuff in each of them is a tedious exercise. I have written a little static class that allows to use fire a notification event from any class (on any thread) using
communication.FireNotification(this, );
The definition of the EventArgsNotification class is also included in this file. It is static so an instantiation is not necessary. To subscribe to the event the same code as above is sufficient. Please don’t forget to correct the namespace to the one of your project.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace example // PUT YOUR NAMESPACE HERE!
{
    public delegate void EventHandlerNotification(object sender, EventArgsNotification e);

    public static class communication
    {
        public static event EventHandlerNotification EventNotification;

        /// 
        /// Fires a 'Notification' Event. The method is static an therefore can be accessed from any class without instantiation.
        /// 
        /// Object that fires the event.
        /// Notification message (free text).
        public static void FireNotification(object sender, string message)
        {
            if (EventNotification != null)
            {
                EventArgsNotification e = new EventArgsNotification();
                e.info_text = message;
                EventNotification(sender, e);
            }
        }
    }

    /// 
    /// A class used to send and receive textual information.
    /// 
    public class EventArgsNotification : EventArgs
    {
        public string info_text;
    }

}

Blog content from http://mklammler.wordpress.com

Saturday, December 18, 2010

Asynchronous Method call Fire and forget

Method I found easy.

Method 1:
System.Threading.ThreadPool.QueueUserWorkItem(c => MethodCall())

Ex:
static void Main(string[] args)
{
Console.WriteLine("Main Thread Start at :" + DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff"));
System.Threading.ThreadPool.QueueUserWorkItem(c => PrintTime());
System.Threading.ThreadPool.QueueUserWorkItem(c => PrintTime());
System.Threading.ThreadPool.QueueUserWorkItem(c => PrintTime());
System.Threading.ThreadPool.QueueUserWorkItem(c => PrintTime());
System.Threading.Thread.Sleep(10000);
Console.WriteLine("Main Thread End at :" + DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff"));
Console.ReadKey();
}

private static void PrintTime()
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff"));
}



Method 2:

System.Threading.Thread obj = new System.Threading.Thread(() => MethodCall(Arg)));
obj.IsBackground = true;
obj.Start();

Ex:

static void Main(string[] args)
{
Console.WriteLine("Main Thread Start at :" + DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff"));
System.Threading.Thread t1 = new System.Threading.Thread(() => PrintTime(DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff")));
System.Threading.Thread t2 = new System.Threading.Thread(() => PrintTime(DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff")));
System.Threading.Thread t3 = new System.Threading.Thread(() => PrintTime(DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff")));
System.Threading.Thread t4 = new System.Threading.Thread(() => PrintTime(DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff")));
System.Threading.Thread t5 = new System.Threading.Thread(() => PrintTime(DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff")));
t1.IsBackground = true;
t2.IsBackground = true;
t3.IsBackground = true;
t4.IsBackground = true;
t5.IsBackground = true;
t1.Start();
t2.Start();
t3.Start();
t4.Start();
t5.Start();
System.Threading.Thread.Sleep(10000);
Console.WriteLine("Main Thread End at :" + DateTime.Now.ToString("YYYY/MM/dd HH:mm:ss.ffffff"));
Console.ReadKey();
}

private static void PrintTime(String CurrentTime)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(CurrentTime);
}

Friday, November 5, 2010

IEnumerable - DataTable Export to Word / Excel / PDF / HTML

I found the codePlex Project Exporter.codeplex.com more useful for my application
where u can export the datatable List to Word / Excel / PDF / HTML.

where it worked for windows Application without an issue.
when i added it to the web application it failed. Here is the fix..
Exporter need to change in code for web and windows application. So its better to determine the type of application accessing it and access the template.
Add reference System.Web; to ExportDLL and declare a Property setter as follows.
public static bool IsWebApplication
{
get
{
try
{
System.Web.HttpContext Context = System.Web.HttpContext.Current;
if (Context != null)
return true;
}
catch { }

return false;
}
}

and in the StringTemplateGroup Check the application is web and set the Server.MapPath for PathFiles
private static StringTemplateGroup stgCollection
{
get
{
string where = @"templates\Collection";
if (IsWebApplication)
PathFiles = System.Web.HttpContext.Current.Server.MapPath("bin");

if (!string.IsNullOrEmpty(PathFiles))
{
where = Path.Combine(PathFiles, where);
}
StringTemplateGroup stg = new StringTemplateGroup("Collection", where);
stg.RegisterAttributeRenderer(typeof(string), new AdvancedStringRenderer());
stg.RegisterAttributeRenderer(typeof(DateTime), new AdvancedDateTimeRenderer());
return stg;
}
}

and here is the link

http://exporter.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=163747