0

我正在制作一个服务器 - 客户端项目。在这里,服务器根据客户端调用对数据库进行更改。客户端调用是异步的。我正在使用事件根据来电调用一些委托。下面的代码可以给你一个想法

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

我在同一个系统中运行两者。我还没有收到任何崩溃。但在实际情况下,客户 => 5 -> 20 。所以问题是如果两个事件同时发生,那么会发生什么?

编辑:

我正在为服务器部分使用第三方库“SuperWebsocket”。这个定义了 message_Received 事件。文档说它是线程安全的。我的是单线程应用程序。只有一个服务器对象。一些函数(由代表调用)有一些长代码。例如拿这个

public void called_By_Some_Delegate(WebSocketSession session, string e)
{
       //1) retrieve a big list from database
       //2) change the list into a dictionary object
       //3) create a string using dictionary object
       //4) send this string to the client using the "session" object
}

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

4

2 回答 2

1

当您同时说时,我有点理解服务器中有多个线程在侦听请求和引发事件。在这种情况下,每个线程都将触发事件,并且事件处理程序将在各自的线程中运行而没有任何问题(假设事件处理程序是线程安全的)。

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

如果侦听线程触发另一个线程来处理传入请求,那么您再次让事件处理程序在其自己的线程上下文中运行,并且只要您的处理程序是线程安全的,那么您仍然是安全的。

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

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

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

于 2012-05-18T15:56:48.553 回答
0

这取决于server调用NewMessageReceived事件的方式。但最可能的情况是它为此使用了一个线程池线程,并且没有防范多次调用。这意味着它可能Client_Logging_In_Function会同时执行两次(或更多)。

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

调用委托和直接调用方法之间的唯一区别是委托调用是间接的(在调用委托时您不选择调用哪个方法,您之前已选择)并且可以同时调用多个方法这种方式(如果委托是多个简单委托的组合)。

于 2012-05-18T15:04:27.677 回答