从不同的类更新(最好通过事件)

本文关键字:事件 更新 | 更新日期: 2023-09-27 18:14:55

我有一个后台工作在我的GUI类。

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    ProgressClass obj = new ProgressClass();
    Importer tradeImporter = e.Argument as Importer;
    BackgroundWorker worker = sender as BackgroundWorker;
    List<TradeUploadInfo> list = obj.AllocateTrades2(tradeImporter, false);
    e.Result = list; //Passes the list for processing
}

Importer是我自己的类。现在,AllocateTrades2方法已经完成了所有的处理。

我的问题是,我该如何在AllocateTrades2方法中执行bw.ProgressReport,这是在一个不同的类中,而不将bw作为参数传递?

如果有人向我解释如何处理事件,那就太好了,但如果有另一种优雅的方式。

从不同的类更新(最好通过事件)

如果您不想传递整个BGW(有理由这样),以便不暴露比它需要知道的更多,一种选择是只传递您分配ReportProgress调用的委托。

AllocateTrades2的签名调整为:

public List<TradeUploadInfo> AllocateTrades2(
    Importer importer, bool flag, Action<int> reportProgress)

在该方法中调用reportProgress委托。

然后将呼叫调整为AllocateTrades2,如下:

obj.AllocateTrades2(tradeImporter, false,
     progress => worker.ReportProgress(progress));

好吧,考虑到AllocateTrades2在后台工作线程的上下文中运行,它引发的任何事件也在该上下文中执行。

所以,你所需要做的就是在你的ProgressClass中添加一个新事件,比如NotifyProgress,并将它绑定到你拥有后台worker的类。

:

 //In class ProgressClass. 
 public event EventHandler<ProgressClassEventArgs> NotifyProgress = (s, e) => {};
下:

 private void bw_DoWork(object sender, DoWorkEventArgs e)
 {
     ProgressClass obj = new ProgressClass();
     //Here you hook up the event
     obj.NotifyProgress += this.OnProgressChanged;
     Importer tradeImporter = e.Argument as Importer;
     BackgroundWorker worker = sender as BackgroundWorker;
     List<TradeUploadInfo> list = obj.AllocateTrades2(tradeImporter, false);
     e.Result = list; //Passes the list for processing
 }

事件处理程序看起来像这样:

private void OnProgressChanged(object sender, ProgressClassEventArgs e) 
{
   worker.ReportProgress(e.Progress);
}

没关系,因为你可以(或者你已经这样做了)把worker作为这个类的成员。

您需要定义ProgressClassEventArgs (EventArgs子类),并在本例中添加一个int类型的Progress属性,以匹配ReportProgress参数。

如果您能够/愿意修改对象。AllocateTrades2方法,您可以yield结果,然后将每个项目添加到循环中的列表。

的例子:

public IEnumerable<TradeUploadInfo> AllocateTrades2(Importer tradeImporter, bool foo)
{
    foreach( ... )
    {
        TradeUploadInfo bar; // = ...
        // ...
        yield return bar;
    }
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    ProgressClass obj = new ProgressClass();
    Importer tradeImporter = e.Argument as Importer;
    BackgroundWorker worker = sender as BackgroundWorker;
    List<TradeUploadInfo> list = new List<TradeUploadInfo>();
    foreach ( TradeUploadInfo info in obj.AllocateTrades2(tradeImporter, false) )
    {
        list.Add( info );
        // ... progress
    }
    e.Result = list; //Passes the list for processing
}
这里的美妙之处在于,您可以完全像以前一样使用AllocateTrades2 (这意味着您不必修改现有代码或重载函数) (嗯…实际上,您需要修改显式地期望使用List的代码,可能只需在函数调用之后添加.ToList()),并且不需要添加事件(当涉及到垃圾收集时,这可能会变得有点棘手)。