2013-04-18 89 views
0

我有一个创建BackgroundWorker的表单。然后,工作人员会做一些工作,并在ReportProgress忙时将消息发送回UI。然后我将这些消息记录到用户界面。 ReportProgress由线程中的单个方法完成,我称之为“通知”。调用常用方法的类 - 委托?

但是,在线程内,我调用静态类来做文件访问类型的工作。这个静态类也需要报告进度......所以我需要调用线程类的Notify方法来调用静态类 - 但是,我无法访问调用类中的方法。

所以,UI创建线程...并且线程使用一个类,但是我需要从静态类调用类中的Notify方法。我怎样才能做到这一点?

这是我的尝试。这个想法是尝试使用委托...但是,我坚持实际使用委托。 :)

在我的线程类,我有一个方法:

public void Notify(string message, Constants.ErrorLevel errorLevel) 
{ 
    var su = new StatusUpdate {StatusMessage = message, ErrorLevel = 0}; 
    _bw.ReportProgress(0, su); 
} 

这是工作。它可以很好地向调用用户界面报告。

我现在在这个类中创建一个委托:

public delegate bool NotificationsDelegate(object MessageHolder); 

我已经改变了我的移交档案管理静态类,非静态的,而且我想,当我到该委托传递给文件管理器类创建:

public class FileManager 
{ 
private readonly NotificationsDelegate _notifications; 

public FileManager(NotificationsDelegate notifications) 
{ 
    _notifications = notifications; 
} 

private void SendMessageBack(string p, ConsoleColor consoleColor) 
{ 
    var su = new StatusUpdate {ErrorLevel = 0, StatusMessage = p}; 
    _notifications(su); 
} 

所以,我创建它,并通过通知委托...然后在我的“SendMessageBack”的方法,希望能够调用该委托(被称为_notifications)。

但这就是我卡住的地方。委托尚未分配给通知方法。我对事件很陌生,所以猜测我的方式。但是,有人可以帮我解决这个问题吗?

+0

将BackgroundWorker传递给静态类中的方法,以便它可以调用ReportProgress? – dtb 2013-04-18 04:12:20

+0

我在想这个,但是每次使用静态方法时,我都必须将bw对象添加到每个调用中? – Craig 2013-04-18 04:17:57

回答

1

如果您计划在线程之间共享FileManager类的一个实例,那么您每次调用它时都必须传入一个委托实例。如果您在每个“线程类”中创建一个FileManager类的新实例,那么您可以按照书面方式向FileManager中的委托人提供该委托。

public delegate void NotifyDelegate(string message, Constants.ErrorLevel errorLevel); 

public class BackgroundWorker { 
    public BackgroundWorker() { 
     _fileMgr = new FileManager(Notify); 
    } 

    public void Notify(string message, Constants.ErrorLevel errorLevel) { 
     // do stuff 
    } 
} 

public class FileManager { 
    public FileManager(NotifyDelegate notification) { 
     _notification = notification; 
    } 

    public void SendMessageBack() { 
     _notification("foo", 0); 
    } 
} 

如果你愿意,你可以只使用拉姆达的,并避免直接创建代表:

public class FileManager { 
    public FileManager(Action<string, Constants.ErrorLevel> notifyAction) { 
     _notification = notifyAction; 
    } 

    public void SendMessageBack() { 
     _notification("foo", 0); 
    } 
} 

public class BackgroundWorker { 
    public BackgroundWorker() { 
     _fileMgr = new FileManager((a, b) => Notify(a, b)); 
    } 
} 
1

我不能肯定我跟着你在做什么,但我会带请查看基于事件的通知系统,以便从您的文件访问工作班级调用Notify方法。我假设你的文件访问工作类叫做FileManager,它是一个实例类。

首先,创建一个自定义EventArg类,用于存储要在FileManager类中发出的通知中要传递的数据。在FileManager类中使用此类定制EventArg类创建一个DoNotify事件,并在您想要更新Notify方法时调用事件(在填充状态数据后)。

当你实例化一个FileManager对象订阅DoNotify事件,并在其处理程序调用你的Notify方法:

public class FileManager 
{ 
    public event EventHandler<NotifyEventArgs> DoNotify; 

    private void DoSomethingInterestingMethod() { 
     //... 

     // Let listeners know something interesting happened. 
     var doNotify = DoNotify; 
     if (doNotify != null) { 
      doNotify(this, new NotifyEventArgs(errorLevel, message)); 
     } 

     //... 
    } 
} 

public class NotifyEventArgs : EventArgs 
{ 
    public NotifyEventArgs(int errorLevel, string statusMessage) { 
     ErrorLevel = errorLevel; 
     StatusMessage = statusMessage; 
    } 

    public int ErrorLevel { get; private set;} 
    public string StatusMessage { get; private set; } 
} 

,然后在你的BackgroundWorker的线程(在DoWork()?)创建一个或多个FileManager对象并订阅DoNotify事件:

var fm = new FileManager(); 
fm.DoNotify += FileManager_Notify; 

而在DoNotify处理程序调用你的Notify方法:

void FileManager_Notify(object sender, NotifyEventArgs e) { 
    Notify(e.ErrorLevel, e.StatusMessage); 
} 

我不能完全肯定你的一些实施细节,所以我希望我做我自己清楚,足以让您评估这一做法,并决定它是否适合你。