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