我有一个对象可以从一瞬间到几分钟进行初始化.原因是构造函数从Web服务检索数据,可能是几千字节到几兆字节,并且根据用户的连接速度,性能可能会有很大差异.出于这个原因,我想把事件放在那将处理进度通知.
这是我的问题:我可以在构造函数中放置事件处理程序,还是应该使用Load方法执行此类操作?
例如:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试将事件处理程序绑定到构造函数时,它们在被调用时始终为null:
MyObject o = new MyObject(1);
o.UpdateLoadProgress += new EventHandler<EventArgs>(o_UpdateLoadProgress);
Run Code Online (Sandbox Code Playgroud)
我认为这是因为我在构造函数之后连接了事件.我看到的唯一选择是创建一个Load方法来完成构造函数的工作.缺点是任何使用此类的人必须知道在尝试访问Result(或任何其他属性)之前调用Load.
编辑: 这是最终的解决方案:
MyObjectBuilder类
public class MyObjectBuilder
{
public event ProgressChangedEventHandler ProgressChanged;
public MyObject CreateMyObject()
{
MyObject o = new MyObject();
o.Load(ProgressChanged);
return o;
}
}
Run Code Online (Sandbox Code Playgroud)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
计划类
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);
}
}
Run Code Online (Sandbox Code Playgroud)
当然,另一种选择是将事件处理程序传递给构造函数.
我个人试图避免在构造函数中做这样的事情.创建新对象通常不应该启动后台任务IMO.您可能希望将其置于静态方法中 - 当然,它可以调用私有构造函数.
您还可以将您的班级分成两部分 - 一个可以准备好所有内容的构建器(例如事件),然后是一个具有该Result属性的"正在运行或已完成"的类.你可以Start在第一堂课上打电话或类似的东西来获得第二堂课的实例.
| 归档时间: |
|
| 查看次数: |
1570 次 |
| 最近记录: |