Event handlers in constructors - is it possible or even wise?

I have an object that can take anywhere from two seconds to several minutes to initialize. The reason is that the designer is retrieving data from the web service, which can range from a few kilobytes to several megabytes, and depending on the connection speed of the user connection, the speed can vary greatly. For this reason, I want to put events in this to handle the progress notification.

Here is my question: can I put an event handlers in the constructor or should this type of action have to be performed using the Load Method?

For example:

public class MyObject { public event EventHandler<UpdateLoadProgressEventArgs> UpdateLoadProgress; public MyObject(int id) { Background worker bgWorker = new BackgroundWorker(); bgWorker.DoWork += delegate(object s, DoWorkEventArgs args) { //load data and update progress incrementally UpdateLoadProgress(this, new UpadteLoadProgressEventArgs(progressValue)); Result = someValue; } bgWorker.RunWorkAsync(); } public int Result { get; set; } } 

However, when I try to associate event handlers with the constructor, they are always zero when called:

 MyObject o = new MyObject(1); o.UpdateLoadProgress += new EventHandler<EventArgs>(o_UpdateLoadProgress); 

I assume this is happening because I am hooking events after the constructor. The only alternative that I see is to create a Load method that does the work of the constructor. The disadvantage is that anyone using this class must know to call Load before trying to access the Result (or any other property).

EDIT: Here is the final solution:

Class MyObjectBuilder

 public class MyObjectBuilder { public event ProgressChangedEventHandler ProgressChanged; public MyObject CreateMyObject() { MyObject o = new MyObject(); o.Load(ProgressChanged); return o; } } 

Class myobject

 public class MyObject { public int Result { get; set;} public void Load(ProgressChangedEventHandler handler) { BackgroundWorker bgWorker = new BackgroundWorker(); bgWorker.WorkerReportsProgress = true; bgWorker.ProgressChanged += handler; bgWorker.DoWork += delegate(object s, DoWorkEventArgs args) { for (int i = 0; i < 100; i++) { Thread.Sleep(10); Result = i; bgWorker.ReportProgress(i); } }; bgWorker.RunWorkerAsync(); } } 

Program class

 class Program { static void Main(string[] args) { MyObjectBuilder builder = new MyObjectBuilder(); builder.ProgressChanged += new ProgressChangedEventHandler(builder_ProgressChanged); MyObject o = builder.CreateMyObject(); Console.ReadLine(); } static void builder_ProgressChanged(object sender, ProgressChangedEventArgs e) { Console.WriteLine(e.ProgressPercentage); } } 
+6
source share
2 answers

Another option would, of course, be to pass event handlers to the constructor as well.

Personally, I try to avoid doing something like this inside the constructor. Creating a new object usually should not start with background tasks, IMO. Instead, you can put it in a static method, which of course can call a private constructor.

You can also split your class into two - the builder who prepares everything (for example, events), and then the class “in flight or completed”, which has the Result property. You would call Start or something similar in the first class to get an instance of the second.

+8
source share

Is it possible? May be. Is it wise? Not.

The most obvious reason is that you are not guaranteed that the background thread will not execute before the event handlers are connected after the object is built. Or, even worse, some of the event handlers may be signed, while others may not.

+1
source share

All Articles