Showing posts with label Events. Show all posts
Showing posts with label Events. Show all posts

Thursday, October 30, 2008

Multithreading and events



Don't you just love Multi-threading, well, I love to see my processor being efficiently used and close to at least 70% utilization. even though threads are dangerous however, using threads carefully will allow your user interface to always be responsive.
Nowthat, we will live with threads, those threads will certainly need to talk to the user interface thread. There are many ways for them to start chit chatting and my prefered way is events.
In this mechanism, a thread will raise an event and anyone who is subscribed to this event will receive the event data and will have a chance to process it.
Here is how to do that.
Let's say you have a calls called "Communicator" which will be processed in a thread and need to raise an event when the thread is done. what you need to do is
1- Define a delegate and an event as follows
//Delegate
public delegate void AlertSentHandler(object sender, SentAlertEventArgs e);
//Event
public event AlertSentHandler AlertSent;
2- Raise the event at the proper time as follows
onAlertSent(this,new SentAlertEventArgs(DateTime.Now.ToString()));
3- Since you are using a helper function called onAlertSent then you need to write it as follows
Protected void onAlertSent(object sender, SentAlertEventArgs e)
{
if (AlertSent != null)
AlertSent(sender, e );
}
The onAlertSent method is checking if the delegate is not null (There are subscribers to the event) and then call the delegate itself as shown above.

Now this event is sent because someone will probably care that the thread is done. those who care that the thread is done should subscribe to the event. To subscribe to this event simply subscribe as follows
cm.AlertSent += new Communicator.AlertSentHandler(cm_AlertSent);
and that is...!!!!!
Note: The above topic is different from serializing the threads (incorrectly called Synchronizing the threads). When you need threads to wait for each others you may want to use the serialization techniques, one of them is the ManualResetEvent
which you may declare like this

static ManualResetEvent threadSerializer = new ManualResetEvent(true );
and make your threads WaitOne like this
threadSerializer.WaitOne();
and set and reset like this
threadSerializer.Reset();
//Do thread work
threadSerializer.Set();
There is a complete and good article about this type of serialization techniques in these links

Friday, September 12, 2008

SCSF Events (One firer and multiple (Not wanted) subscribers)

So when working with SCSF you may face a problem like this.

You have built two views as part of a module (View1 and View2). View1 fires an event that View2 is  subscribed to. this all seems very legal until now. but what if View2 and View2 are loaded and displayed more than one time. now comes the illegal part. every time any of the View1 fires the event, all instances of View2 will receive it and react to it.

To illustrate it even further, assume you have built a hospital application that consists of two views. SearchView and DisplayView. the search view allows the user to search for a patient by specifying part of the patient name. but the SearchView does not display the search result, it is the DisplpayView that displays the results after receiving the Event showResults. now when the user types part of the patient name and click search, the event ShowResults will be raised and DisplayView will receive it. DisplayView will use the EventArgs to find the patient and then display him/her. the problem happens if you loaded two of the SearchView and two of the DisplayView. now when you type part of the paient name in any of the SearchView loaded and click Search, both of the loaded DisplayView will receive this event and will display this patient.

The solution to this problem is to make your module create a new work item every time it wants to add views. then add the views (SearchView and DisplayView) to this new work item.

when you fire the event you fire the event to the subscribers within the work item.
Here is how.
in your ModuleController.cs declare a new workitem as follows

WorkItem instancewi = new WorkItem();

Next, in the AddViews method add this new workitem to the WorkItems collection of the current item

instancewi = WorkItem.WorkItems.AddNew<WorkItem>();

now when adding views add then in this new workitem as follows

instancewi.SmartParts.AddNew<WhateverYourViewIs>();


now when firing an event, you should always be limiting the scope to the work item using PublicationScope.WorkItem enumeration and specifying the current workitem as follows

WorkItem.EventTopics[WhateverYourTopicIs].Fire(this,new EventArgs(WhaeteverWahtever), WorkItem, PublicationScope.WorkItem);

This way when you fire an event from one view, only the other views that were loaded with the same view will receive this event, since they are in the same workitem.
Hope that helps.