C# 将委托将所有事件排队并逐个执行

C# 将委托将所有事件排队并逐个执行,c#,windows,asynchronous,delegates,client-server,C#,Windows,Asynchronous,Delegates,Client Server,我正在做一个服务器客户端项目。在这里,服务器根据客户端调用在数据库中进行更改。客户端调用是异步的。我正在使用事件根据传入呼叫调用一些委托。下面的代码可以给你一些想法 public delegate void Client_Logging_In_Delegate(WebSocketSession session, string e); public event Client_Logging_In_Delegate Admin_Logging_In_Event; public void Client

我正在做一个服务器客户端项目。在这里,服务器根据客户端调用在数据库中进行更改。客户端调用是异步的。我正在使用事件根据传入呼叫调用一些委托。下面的代码可以给你一些想法

public delegate void Client_Logging_In_Delegate(WebSocketSession session, string e);
public event Client_Logging_In_Delegate Admin_Logging_In_Event;
public void Client_Logging_In_Function(WebSocketSession session, string e)
{
    //Database -> this particular client status= true
}

public void Main()
{
    server.NewMessageReceived += new SessionEventHandler<WebSocketSession, string>     (server.WebSocketServer_NewMessageReceived);

    server.Client_Logging_In_Event = new Client_Logging_In_Delegate(server.Client_Logging_In_Function);
}

public void WebSocketServer_NewMessageReceived(WebSocketSession session, string e)
{
    string type = e.Substring(0, e.IndexOf("#"));
    if (type == "Client_Logging_In")
        Client_Logging_In_Event(session, e);
}

现在,假设同一委托/函数有两个事件到达。现在假设第一个将执行函数,它在第二个点执行。如果第二个同时访问该函数,它将更改列表。所以,我认为会有一场崩溃。这就是我必须弄清楚的情况。

这取决于
服务器如何准确地调用
NewMessageReceived
事件。但最有可能的情况是,它为此使用了一个线程池线程,并且没有防止多次调用。这意味着,
Client\u Logging\u In\u函数
可能同时执行两次(或更多)

调用委托(无论它是否来自事件)与调用普通方法非常相似:没有锁定或排队,它直接在当前线程上调用(除非使用
BeginInvoke()


调用委托和直接调用方法之间的唯一区别在于委托调用是间接的(在调用委托时,您没有选择要调用的方法,而是在前面选择了该方法),并且可以通过这种方式同时调用多个方法(如果代理是多个简单代理的组合).

如果您同时说,我可以理解,服务器中有多个线程侦听请求并引发事件。在这种情况下,每个线程都将触发事件,并且事件处理程序将在各自的线程中运行,不会出现任何问题(前提是事件处理程序是线程安全的)

如果没有,并且只有一个线程在侦听套接字,那么无论如何,您是顺序的,不应该有问题

如果侦听线程触发另一个线程来处理传入的请求,那么事件处理程序也可以在它自己的线程上下文中运行,只要处理程序是线程安全的,那么您仍然是安全的

我编写了下面的程序来模拟服务器生成多个请求并处理相同的请求

using System;
using System.Threading;
namespace AsyncFiber
{
    class Program
    {
        public event EventHandler<int> ClientEventReceived;
        public event EventHandler<int> MessageProcessed;
        static void Main(string[] args)
        {
            Program p = new Program();
            p.ClientEventReceived += p.p_ClientEventReceived;
            p.MessageProcessed += p.p_MessageProcessed;
            for (int i = 0; i < 5; i++)
                new Thread(new ThreadStart(p.target)).Start();
        }
        private void p_MessageProcessed(object sender, int e)
        {
            PrintHelper("C->" + e);
        }

        private void p_ClientEventReceived(object sender, int e)
        {
            MessageProcessed(sender, e);
        }

        void target()
        {
            while (true)
            {
                var data = new Random().Next();
                Console.WriteLine("P->" + data);
                ClientEventReceived(Thread.CurrentThread.Name, data);
            }
        }

        void PrintHelper(string message)
        {
            for (int i = 0; i < Thread.CurrentThread.ManagedThreadId; i++)
                Console.Write("  ");
            Console.Write(message);
            Console.WriteLine();
        }
    }
}
使用系统;
使用系统线程;
名称空间异步光纤
{
班级计划
{
公共事件处理程序客户端已接收;
已处理公共事件事件处理程序消息;
静态void Main(字符串[]参数)
{
程序p=新程序();
p、 客户接受+=p.p_客户接受;
p、 MessageProcessed+=p.p_MessageProcessed;
对于(int i=0;i<5;i++)
新线程(新线程开始(p.target)).Start();
}
私有void p_MessageProcessed(对象发送方,int e)
{
PrintHelper(“C->”+e);
}
私有无效p_客户端已接收(对象发送方,int e)
{
MessageProcessed(发送者,e);
}
无效目标()
{
while(true)
{
var data=new Random().Next();
Console.WriteLine(“P->”+数据);
ClientEventReceived(Thread.CurrentThread.Name,数据);
}
}
无效PrintHelper(字符串消息)
{
for(int i=0;i

因此,为了回答您的问题,事件处理程序将在各自的线程中同时执行。但是,数据库锁定方案应足够清晰,以处理此情况。

您发布的代码中不会发生任何事情。这是线程安全的,因为您不使用任何共享资源(服务器对象除外)例如,您应该在函数代码中发布客户端日志,并提供NewMessageReceived事件的实现。我没有实现“NewMessageReceived”。这是由第三方库“SuperWebSocket”提供的。文档中说它是线程安全的。上面的代码只是一个存根。在函数=>中的实际代码中,我必须显示一条消息,并在数据库中进行更改。然后我必须向客户端发送一个回复。因此是否存在争用条件的可能性?是否会错过任何事件?我使用的是单个服务器对象,应用程序正在运行单线程。请看编辑。然后在这种情况下,事件无论如何都是按顺序接收的,并且是有保证的,我猜。所以你应该很好。
using System;
using System.Threading;
namespace AsyncFiber
{
    class Program
    {
        public event EventHandler<int> ClientEventReceived;
        public event EventHandler<int> MessageProcessed;
        static void Main(string[] args)
        {
            Program p = new Program();
            p.ClientEventReceived += p.p_ClientEventReceived;
            p.MessageProcessed += p.p_MessageProcessed;
            for (int i = 0; i < 5; i++)
                new Thread(new ThreadStart(p.target)).Start();
        }
        private void p_MessageProcessed(object sender, int e)
        {
            PrintHelper("C->" + e);
        }

        private void p_ClientEventReceived(object sender, int e)
        {
            MessageProcessed(sender, e);
        }

        void target()
        {
            while (true)
            {
                var data = new Random().Next();
                Console.WriteLine("P->" + data);
                ClientEventReceived(Thread.CurrentThread.Name, data);
            }
        }

        void PrintHelper(string message)
        {
            for (int i = 0; i < Thread.CurrentThread.ManagedThreadId; i++)
                Console.Write("  ");
            Console.Write(message);
            Console.WriteLine();
        }
    }
}