C# 如何改进和/或模块化处理基于事件的任务?

C# 如何改进和/或模块化处理基于事件的任务?,c#,events,asynchronous,C#,Events,Asynchronous,所以我有一个服务器,我通过一个包装好的WebSocket(WebSocket4Net)调用它,我正在构建的库的一个要求是能够等待请求的返回。因此,我有一个MessageEventHandler类,它包含消息传入时由MessageHandler类触发的事件 MessageEventHandler-ex public class MessageEventHandler : IMessageEventHandler { public delegate void NodeName

所以我有一个服务器,我通过一个包装好的WebSocket(WebSocket4Net)调用它,我正在构建的库的一个要求是能够等待请求的返回。因此,我有一个MessageEventHandler类,它包含消息传入时由MessageHandler类触发的事件

MessageEventHandler-ex

public class MessageEventHandler : IMessageEventHandler
    {
        public delegate void NodeNameReceived(string name);

        public event Interfaces.NodeNameReceived OnNodeNameReceived;

        public void NodeNameReceive(string name)
        {
            if (this.OnNodeNameReceived != null)
            {
                this.OnNodeNameReceived(name);
            }
        }
    }
public class MessageHandler : IMessageHandler
    {
        private IMessageEventHandler eventHandler;

        public MessageHandler(IMessageEventHandler eventHandler)
        {
            this.eventHandler = eventHandler;
        }

        public void ProcessDataCollectorMessage(string message)
        {
            var serviceMessage = JsonConvert.DeserializeObject<ServiceMessage>(message);

            switch (message.MessageType)
            {
                case MessageType.GetNodeName:
                    {
                        var nodeName = serviceMessage.Data as string;

                        if (nodeName != null)
                        {
                            this.eventHandler.NodeNameReceive(nodeName);
                        }

                        break;
                    }
                default:
                {
                    throw new NotImplementedException();
                }
             }
         }
MessageHandler示例

public class MessageEventHandler : IMessageEventHandler
    {
        public delegate void NodeNameReceived(string name);

        public event Interfaces.NodeNameReceived OnNodeNameReceived;

        public void NodeNameReceive(string name)
        {
            if (this.OnNodeNameReceived != null)
            {
                this.OnNodeNameReceived(name);
            }
        }
    }
public class MessageHandler : IMessageHandler
    {
        private IMessageEventHandler eventHandler;

        public MessageHandler(IMessageEventHandler eventHandler)
        {
            this.eventHandler = eventHandler;
        }

        public void ProcessDataCollectorMessage(string message)
        {
            var serviceMessage = JsonConvert.DeserializeObject<ServiceMessage>(message);

            switch (message.MessageType)
            {
                case MessageType.GetNodeName:
                    {
                        var nodeName = serviceMessage.Data as string;

                        if (nodeName != null)
                        {
                            this.eventHandler.NodeNameReceive(nodeName);
                        }

                        break;
                    }
                default:
                {
                    throw new NotImplementedException();
                }
             }
         }


或者,如果我的方法实际上是“好的”,那么有谁能提供一些建议,告诉我如何编写一个助手函数来抽象出以这种方式设置每个函数?任何帮助都将不胜感激。

对于初学者,请遵循线程安全模式:

    public void NodeNameReceive(string name)
    {
        var evt = this.OnNodeNameReceived;
        if (evt  != null)
        {
            evt (name);
        }
    }

如果不引用事件对象,则可以在检查null和调用该方法之间将其设置为null。

因此我编写了几个类来解决我遇到的问题。第一个是我的CallbackHandle类,它包含TaskCompletionSource中的任务,因此每次在我的示例中发出请求时,都会创建一个新的回调句柄

public class CallbackHandle<T>
{
    public CallbackHandle(int timeout)
    {
        this.TaskCompletionSource = new TaskCompletionSource<T>();

        var cts = new CancellationTokenSource(timeout);

        cts.Token.Register(
            () =>
                {
                    if (this.Cancelled != null)
                    {
                        this.Cancelled();
                    }
                });

        this.CancellationToken = cts;
    }

    public event Action Cancelled;

    public CancellationTokenSource CancellationToken { get; private set; }

    public TaskCompletionSource<T> TaskCompletionSource { get; private set; }
}
公共类回调句柄
{
公共回调句柄(int超时)
{
this.TaskCompletionSource=新的TaskCompletionSource();
var cts=新的CancellationTokenSource(超时);
cts.Token.Register(
() =>
{
如果(this.Cancelled!=null)
{
这个。取消();
}
});
this.CancellationToken=cts;
}
公众活动取消;
public CancellationTokenSource CancellationToken{get;private set;}
public TaskCompletionSource TaskCompletionSource{get;private set;}
}
然后我有一个“处理程序”来管理句柄及其创建

public class CallbackHandler<T>
{
    private readonly IList<CallbackHandle<T>> callbackHandles;

    private readonly object locker = new object();

    public CallbackHandler()
    {
        this.callbackHandles = new List<CallbackHandle<T>>();
    }

    public CallbackHandle<T> AddCallback(int timeout)
    {
        var callback = new CallbackHandle<T>(timeout);

        callback.Cancelled += () =>
            {
                this.callbackHandles.Remove(callback);
                callback.TaskCompletionSource.TrySetResult("Error");
            };

        lock (this.locker)
        {
            this.callbackHandles.Add(callback);
        }

        return callback;
    }

    public void EventTriggered(T eventArgs)
    {
        lock (this.locker)
        {
            if (this.callbackHandles.Count > 0)
            {
                CallbackHandle<T> callback =
                    this.callbackHandles.First();

                if (callback != null)
                {
                    this.callbackHandles.Remove(callback);

                    callback.TaskCompletionSource.SetResult(eventArgs);
                }
            }
        }
    }
}
公共类回调处理程序
{
私有只读IList回调句柄;
私有只读对象锁定器=新对象();
公共回调处理程序()
{
this.callbackHandles=new List();
}
公共CallbackHandle AddCallback(int超时)
{
var callback=新的CallbackHandle(超时);
回调。已取消+=()=>
{
this.callbackHandles.Remove(回调);
callback.TaskCompletionSource.TrySetResult(“错误”);
};
锁(这个柜子)
{
this.callbackHandles.Add(回调);
}
返回回调;
}
已触发公共无效事件(T事件参数)
{
锁(这个柜子)
{
如果(this.callbackHandles.Count>0)
{
回调句柄回调=
this.callbackHandles.First();
if(回调!=null)
{
this.callbackHandles.Remove(回调);
callback.TaskCompletionSource.SetResult(eventArgs);
}
}
}
}
}
这是我实际实现的一个简化版本,但是如果有人需要类似的东西,应该可以开始使用它。因此,在我的示例中,要在我的ClientServiceInterface类上使用它,我首先要创建一个类级处理程序,并像这样使用它:

public class ClientServiceInterface : IClientServiceInterface
{
private readonly CallbackHandler<string> getNodeNameHandler;

public ClientServiceInterface(IMessageEventHandler messageEventHandler, int responseTimeout = 5000)
    {
        this.messageEventHandler = messageEventHandler;
        this.ResponseTimeout = responseTimeout;

        this.getNodeNameHandler = new
CallbackHandler<string>();

        this.messageEventHandler.OnNodeNameReceived += args => this.getNodeNameHandler.EventTriggered(args);
    }

public Task<string> GetNodeNameAsync()
    {
        CallbackHandle<string> callbackHandle = this.getNodeNameHandler.AddCallback(this.ResponseTimeout);

        var serviceMessage = new ServiceMessage
                                 {
                                     Type = MessageType.GetNodeName.ToString()
                                 };
        this.ReadyMessage(serviceMessage);

        return callbackHandle.TaskCompletionSource.Task;
    }

// Rest of class declaration removed for brevity
}
公共类ClientServiceInterface:IClientServiceInterface
{
私有只读回调处理程序getNodeNameHandler;
公共ClientServiceInterface(IMessageEventHandler messageEventHandler,int-responseTimeout=5000)
{
this.messageEventHandler=messageEventHandler;
this.ResponseTimeout=ResponseTimeout;
this.getNodeNameHandler=新建
CallbackHandler();
this.messageEventHandler.OnNodeNameReceived+=args=>this.getNodeNameHandler.EventTriggered(args);
}
公共任务getNodeNameSync()
{
CallbackHandle CallbackHandle=this.getNodeNameHandler.AddCallback(this.ResponseTimeout);
var serviceMessage=新serviceMessage
{
Type=MessageType.GetNodeName.ToString()
};
这是ReadyMessage(serviceMessage);
返回callbackHandle.TaskCompletionSource.Task;
}
//为简洁起见,删除了类的其余部分声明
}
这比我以前拥有的要好看得多(至少在我看来),而且很容易扩展

public class ClientServiceInterface : IClientServiceInterface
{
private readonly CallbackHandler<string> getNodeNameHandler;

public ClientServiceInterface(IMessageEventHandler messageEventHandler, int responseTimeout = 5000)
    {
        this.messageEventHandler = messageEventHandler;
        this.ResponseTimeout = responseTimeout;

        this.getNodeNameHandler = new
CallbackHandler<string>();

        this.messageEventHandler.OnNodeNameReceived += args => this.getNodeNameHandler.EventTriggered(args);
    }

public Task<string> GetNodeNameAsync()
    {
        CallbackHandle<string> callbackHandle = this.getNodeNameHandler.AddCallback(this.ResponseTimeout);

        var serviceMessage = new ServiceMessage
                                 {
                                     Type = MessageType.GetNodeName.ToString()
                                 };
        this.ReadyMessage(serviceMessage);

        return callbackHandle.TaskCompletionSource.Task;
    }

// Rest of class declaration removed for brevity
}