Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 构造器中的事件处理程序-可能还是明智?_.net - Fatal编程技术网

.net 构造器中的事件处理程序-可能还是明智?

.net 构造器中的事件处理程序-可能还是明智?,.net,.net,我有一个对象,可以在任何地方从一瞬间到几分钟进行初始化。原因是构造函数从Web服务检索的数据可能是几千字节到几百万字节,并且根据用户的连接速度,性能可能会有很大的不同。出于这个原因,我想把事件,将处理进度通知 我的问题是:我能把这个事件 构造函数中的处理程序或 这种类型的操作可以通过 加载方法 例如: public class MyObject { public event EventHandler<UpdateLoadProgressEventArgs> UpdateLo

我有一个对象,可以在任何地方从一瞬间到几分钟进行初始化。原因是构造函数从Web服务检索的数据可能是几千字节到几百万字节,并且根据用户的连接速度,性能可能会有很大的不同。出于这个原因,我想把事件,将处理进度通知

我的问题是:我能把这个事件 构造函数中的处理程序或 这种类型的操作可以通过 加载方法

例如:

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;
 }

} 
MyObject类

public class MyObjectBuilder
    {
        public event ProgressChangedEventHandler ProgressChanged;

        public MyObject CreateMyObject()
        {
            MyObject o = new MyObject();
            o.Load(ProgressChanged);

            return o;
        }
    }
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();                      
        }
    }
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);
        }
    }

当然,另一种选择是将事件处理程序也传递给构造函数

就我个人而言,我尽量避免在构造函数中做这样的事情。依我看,创建一个新对象通常不应该启动后台任务。你可能想把它放进一个静态方法中——当然,它可以调用一个私有构造函数


您还可以将类分为两个部分—一个是准备好所有内容(例如事件)的生成器,另一个是“正在运行或已完成”的类,该类具有
Result
属性。您可以在第一个类上调用
Start
或类似的方法来获取第二个类的实例。

这可能吗?大概这明智吗?没有


最明显的原因是,不能保证在构建对象之后,在事件处理程序连接之前,后台线程不会执行。或者更糟糕的是,一些事件处理程序可能已订阅,而另一些则未订阅。

我通常发现构造函数加载数据是个坏主意。你迟早会后悔的——如果你做单元测试,它会“更快”。@Jon我试图尝试一下你使用Builder类的想法。不过,我认为我不理解这个概念。我将事件处理程序传递给MyObjectBuilder,然后使用create方法返回一个MyObject。不幸的是,MyObject尚未完全加载。你对我上面的代码有什么改动吗?@Blake:好吧,我不想麻烦将事件作为MyObject的一部分-我只想将处理程序传递到构造函数中(从MyObjectBuilder.CreateMyObject)。然而,这看起来基本上应该是可行的。。。发生了什么事?(请注意,您在该代码中混合了这两种方法-如果您对示例代码从一开始就传入事件处理程序感到满意,那么您可以在一种类型中完成这一切,可能是使用静态方法。生成器的思想是让您构造它,添加事件处理程序,然后调用Create方法。)@Jon主要的问题是,在Console.WriteLine(o.Result)点上,输出是0,而不是预期的99(在循环完成之后)。进度正在正确更新,只是对象没有完全初始化。让对象完全初始化是我应该拥有的设计目标,还是构建器模式理解它仍在构建过程中?@Jon-我更正为更正确地使用构建器模式,因此我没有混合这两种方法。请让我知道这是否更符合你的想法。@Blake:嗯。。。循环完成后,应正确更新结果。你肯定是在后台工作人员完成后才检查的吗?诚然,在波动性等方面存在一些问题(你可能想让你的房产成为一个由波动性变量支持的完整房产),但我希望它能起作用。我现在无法调查,但我稍后会看一看。请注意,在您显示的代码中,您正在直接打印结果,即在后台工作人员完成之前。我希望打印0。
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);
        }
    }