将事件处理程序作为参数传递

7

好的,我不太清楚我的代码出了什么问题,也不知道发生了什么事情。

Activity类 有以下方法:

protected struct EventParams
    {
        public object sender;
        public EventArgs e;
    }
private EventParams WaitEventRaise_Body(ref EventHandler<EventArgs> handler, int timeout)
    {
        AutoResetEvent receiver = new AutoResetEvent(false);
        EventParams result = new EventParams();

        EventHandler<EventArgs> handle = new EventHandler<EventArgs>((sender, e) =>
        {
            result.e = e;
            result.sender = sender;
            receiver.Set();
        });

        handler += handle;

        if (timeout > 0)
        {
            receiver.WaitOne(timeout);
        }
        else
        {
            receiver.WaitOne();
        }

        return result;
    }

protected EventParams WaitEventRaise(ref EventHandler<EventArgs> handler)
{
    return WaitEventRaise_Body(ref handler, -1);
}
protected EventParams WaitEventRaise(ref EventHandler<EventArgs> handler, int timeout)
{
    return WaitEventRaise_Body(ref handler, timeout);
}

好的,我发现自己一遍又一遍地写AutoResetEvent这个东西,所以我决定创建一个方法。但是当我试图从派生类 Bot: Activity 调用此方法时,出现了问题。

EventParams eventResult = WaitEventRaise(ref currentJob.JobReported);

提供

错误30:方法“Project.Activity.WaitEventRaise(ref System.EventHandler)”的最佳重载匹配存在一些无效参数

currentJob是一个Job : Activity类,它具有该事件

public event EventHandler<JobReport> JobReported;

并且

class JobReport : EventArgs

我想做的是有一个机器人可以执行任务,实际上是创建任务并等待它们完成工作。任务类在内部触发事件,让机器人类知道它完成了工作。机器人类会等待任务触发事件。希望这样清楚明了。很抱歉我的母语不是英语。


EventHandler<JobReport> 无法被推断为 EventHandler<EventArgs>,因此这样不起作用。 - James
这个对于JobReport不起作用吗?类JobReport : EventArgs。 - user1046403
我尝试了以下代码:EventParams eventResult = WaitEventRaise(ref currentJob.test);其中public event EventHandler<EventArgs> test;但是它给出了错误提示:事件“test”只能出现在“+=”的左侧等等。 - user1046403
主要问题是您无法传递一个 引用(reference) 给事件处理程序,您只能传递一份拷贝。 - James
2个回答

10
基本上,你不能这样引用事件。有两个选项:
  • Pass in delegates for "adding a handler" and "removing a handler":

    EventParams eventResult = 
        WaitEventRaise<JobReport>(handler => currentJob.JobReported += handler,
                                  handler => currentJob.JobReported -= handler);
    

    where WaitEventRaise would be declared as:

    EventParams WaitEventRaise<T>(Action<EventHandler<T>> add,
                                  Action<EventHandler<T>> remove)
                                 where T : EventArgs
    
  • Pass in the EventInfo corresponding to the event, which you'd fetch with reflection

两者都不是非常愉快的 - 这也是 Rx 面临的问题。


但是难道没有一个简短的解决方案吗?我的意思是我不得不一遍又一遍地写这些东西。难道没有一个解决方案,我只需要传递我要处理的内容并接收结果吗?只需要一个方法就可以了。 - user1046403
1
@user1046403:不是的。基本上,在C#中,事件本身不是一等实体(属性、构造函数也不是……方法通过方法组转换有点像)。 - Jon Skeet
@user1046403:请不要添加无意义的评论来吸引注意力。恰巧我已经在回复你的评论了 - 但是在未来,如果我感觉你像这样试图纠缠我,我会明确地回复。这不是我唯一要做的事情。 - Jon Skeet
@JonSkeet 我正在努力弄清楚如何实际调用添加和移除操作。根据签名,在调用期间需要传递类型为 EventHandler<T> 的参数。 - pnizzle
@pnizzle:恐怕我不明白你的意思。建议你提出一个带有 [mcve] 的新问题。 - Jon Skeet

0
我不知道什么是Job类包含的内容或者currentJob.JobReported是什么,但从错误来看,WaitEventRaise方法需要System.EventHandler,这是一种像方法的东西。
private void MeMethod(object sender, EventArgs e)
{
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接