0

我有一个创建 BackgroundWorker 的表单。然后,worker 做一些工作,并在忙碌时执行 ReportProgress 将消息发送回 UI。然后我将这些消息记录到 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);
}

这是有效的。它很好地向调用 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);
}

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

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

4

2 回答 2

1

如果您计划在线程之间共享 FileManager 类的一个实例,那么是的,您绝对必须在每次调用它时传入一个委托实例。如果您在每个“线程类”中创建 FileManager 类的新实例,那么您可以在您编写的 ctor 中为 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);
    }
}

如果您愿意,您可以只使用 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));
    }
}
于 2013-04-18T04:51:06.767 回答
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);
}

我不完全确定你的一些实现细节,所以我希望我已经足够清楚地让你评估这种方法并决定它是否适合你。

于 2013-04-18T05:38:25.547 回答