调用常用方法的类 - 委托?

时间:2013-04-18 03:53:44

标签: c# multithreading class

我有一个创建BackgroundWorker的表单。然后,工作人员执行一些工作,并在报告忙时将ReportProgress发送回UI。然后我将这些消息记录到UI。 ReportProgress由线程中的一个方法完成,我称之为“Notify”。

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

因此,UI创建了线程......并且线程使用了一个类,但是我需要从静态类中调用类中的Notify方法。我怎么能这样做?

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

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

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

这很有效。它可以很好地报告调用UI。

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

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

所以,我创建它,并传递Notification委托......然后在我的'SendMessageBack'方法中,希望调用委托(称为_notifications)。

但那就是我被困住的地方。委托尚未分配给notify方法。我是新手,所以猜测我的方式。但是,有人可以帮助我做到这一点吗?

2 个答案:

答案 0 :(得分:1)

如果您打算在线程之间共享一个FileManager类实例,那么您每次调用它时都必须传入一个委托实例。如果在每个“线程类”中创建FileManager类的新实例,那么您可以在编写时将文件管理器委托给ctor。

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

如果你想要,你可以使用lambda,并避免直接创建委托:

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 :(得分:1)

我不确定我正在关注你正在做什么,但我会看一下基于事件的通知系统,用于从文件访问工作类中调用Notify方法。我假设你的文件访问工作类被称为FileManager并且它是一个实例类。

首先,创建一个自定义EventArg类,以便在FileManager类的通知中存储要中继的数据。在DoNotify班级中使用此自定义FileManager课程创建EventArg个活动,并在您希望更新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);
}

我不完全确定您的某些实施细节,所以我希望自己已经足够明确,让您评估这种方法并确定它是否适合您。