对于基于网络的项目,我需要锁定一些代码以防止同时访问。
这是我的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utility;
using DataBaseConnection;
using System.Net.Sockets;
using System.Data;
using System.IO;

namespace SunHavenClasses
{
    public delegate void CtatReceiveDelegate(string message);
    public class ServerHandlerClass
    {
        public event CtatReceiveDelegate OnChatDataReceive;
        private Settings settings;
        private DBCon con;
        private Utility.Network.Server server;
        private Dictionary<string, Socket> UsersOnline;
        private Dictionary<string, int> unAuthenticatedIps;
        private string pass = "logisoftlogicielbarundipankar";
        public ServerHandlerClass(Settings s)
        {
            settings = s;
            con = s.GetConnection();
            server = new Utility.Network.Server(7777);
            server.ClientConnectEventArise += OnUserConnect;//.OnClientConnect(OnUserConnect);
            server.ClientDataReceiveEventArise += OnUsersDataReceive;
            server.ClientDataSendEventArise += OnDataSendToUser;
            server.ClientDisconnectEventArise += OnUserDisconnect;
            server.OnBlockUser += OnUserBlocked;

            UsersOnline = new Dictionary<string, Socket>();
            unAuthenticatedIps = new Dictionary<string, int>();
        }

        private void OnUserConnect(Utility.Network.ServerEventArguments e)
        {
            Stream data = Utility.Serializing.Serialize(settings);
            data = ZipNEncrypt.Zip(new string[] { "settings" }, new Stream[] { data }, pass);
            server.Send(data, e.ClientSocket);
            //MessageBox.Show(e.ClientSocket.RemoteEndPoint.ToString() + " is Connected!!");
        }
        private void OnUsersDataReceive(Utility.Network.ServerEventArguments e)
        {
            Dictionary<string, System.IO.Stream> data = ZipNEncrypt.Unzip(e.Data, pass);
            User user;
            try
            {
                user = (User)Serializing.Deserialize(data["user"]);
                if (!UsersOnline.ContainsKey(user.GetUserId()))
                {
                    server.BlockIp(e.ClientSocket);
                    return;
                }
                data.Remove("user");
            }
            catch (Exception)
            {
                bool passed = true;
                foreach (string key in data.Keys)
                {
                    if (key.Equals("LoggedIn")) break;
                    string[] str = key.Split('_');
                    if (str[0].Equals("GetData"))
                    {
                        string strr = (string)Serializing.Deserialize(data[key]);
                        if (strr.Contains("Users"))
                        {
                            string ip = e.ClientSocket.RemoteEndPoint.ToString().Split(':')[0];
                            /*CHANGE 1.2.10 00:14*/
                            lock (unAuthenticatedIps)
                            {
                                if (!unAuthenticatedIps.ContainsKey(ip))
                                {
                                    unAuthenticatedIps.Add(ip, 1);
                                }
                                else unAuthenticatedIps[ip] += 1;
                                if (unAuthenticatedIps[ip] >= 11) passed = false;
                            }
                            /*CHANGE 1.2.10 00:14*/
                            break;
                        }
                        else passed = false;//server.AddBlockedIp(ip);
                    }
                    else passed = false;
                }
                if (!passed)
                {
                    server.BlockIp(e.ClientSocket);
                }
            }


            foreach (string key in data.Keys)
            {
                if (key.Equals("LoggedIn"))
                {
                    try
                    {
                        User u = (User)Serializing.Deserialize(data["LoggedIn"]);
                        if (!UsersOnline.ContainsKey(u.GetUserId()))
                        {
                            if (User.ValidateUser(u.GetUserId(), u.GetPassword(), con))
                            {
                                /*CHANGE 1.2.10 00:14*/
                                lock (UsersOnline)
                                {
                                    UsersOnline.Add(u.GetUserId(), e.ClientSocket);
                                    string ip = e.ClientSocket.RemoteEndPoint.ToString().Split(':')[0];
                                    Utility.Log.Write("UserLog.log", u.GetUserId() +
                                        " Logged In From Ip " + ip);
                                }
                                /*CHANGE 1.2.10 00:14*/
                            }
                            else
                            {
                                server.BlockIp(e.ClientSocket);
                                return;
                            }
                        }
                        else
                        {
                            Stream tmpStream = Serializing.Serialize("Same User");
                            tmpStream = ZipNEncrypt.Zip(new string[] { key + "ERROR_SameUser" },
                                        new Stream[] { tmpStream }, pass);
                            server.Send(tmpStream, e.ClientSocket);
                            return;
                        }
                    }
                    catch (Exception) { }
                    return;
                }
                else if (key.Equals("chat"))
                {
                    string ip = e.ClientSocket.RemoteEndPoint.ToString().Split(':')[0];
                    string message = ip + " : "+ (string)Serializing.Deserialize(data[key]);
                    OnChatDataReceive(message);
                    return;
                }
                string[] str = key.Split('_');
                Stream dataStream = null;
                object obj = null;
                try
                {
                    if (str[0].StartsWith("Get"))
                    {
                        if (str[0].Equals("GetData"))
                        {
                            string query = (string)Serializing.Deserialize(data[key]);
                            obj = con.GetData(query);
                        }
                        else if (str[0].Equals("GetColumn"))
                        {
                            string query = (string)Serializing.Deserialize(data[key]);
                            string[] tmp = query.Split('%');
                            obj = con.GetColumn(tmp[0], tmp[1]);
                        }
                        else if (str[0].Equals("GetColumnDistrinctValue"))
                        {
                            string query = (string)Serializing.Deserialize(data[key]);
                            string[] tmp = query.Split('%');
                            obj = con.GetColumnDistrinctValue(tmp[0], tmp[1]);
                        }
                    }
                    else
                    {
                        lock (this)
                        {
                            if (str[0].Equals("ExecuteUpdate"))
                            {
                                if (str[1].Equals("Query"))
                                {
                                    Query query = (Query)Serializing.Deserialize(data[key]);
                                    obj = con.ExecuteUpdate(query);
                                }
                                else if (str[1].Equals("String"))
                                {
                                    string query = (string)Serializing.Deserialize(data[key]);
                                    obj = con.ExecuteUpdate(query);
                                }
                            }
                            else if (str[0].Equals("ExecuteBatchUpdate"))
                            {
                                if (str[1].Equals("Query"))
                                {
                                    Query[] query = (Query[])Serializing.Deserialize(data[key]);
                                    obj = con.ExecuteBatchUpdate(query);
                                }
                                else if (str[1].Equals("String"))
                                {
                                    string[] query = (string[])Serializing.Deserialize(data[key]);
                                    obj = con.ExecuteBatchUpdate(query);
                                }
                            }
                            else if (str[0].Equals("ExecutrInsert"))
                            {
                                Query query = (Query)Serializing.Deserialize(data[key]);
                                obj = con.ExecutrInsert(query);
                            }
                        }
                    }
                    dataStream = Serializing.Serialize(obj);
                    dataStream = ZipNEncrypt.Zip(new string[] { key },
                                new Stream[] { dataStream }, pass);
                }
                catch (Exception ex)
                {
                    dataStream = Serializing.Serialize(ex.Message);
                    dataStream = ZipNEncrypt.Zip(new string[] { key + "_ERROR" },
                                new Stream[] { dataStream }, pass);
                }
                server.Send(dataStream, e.ClientSocket);
            }
        }
        private void OnDataSendToUser(Utility.Network.ServerEventArguments e)
        {
        }
        private void OnUserDisconnect(Utility.Network.ServerEventArguments e)
        {
            //System.Windows.Forms.MessageBox.Show("Disconnected");
            string ip = e.ClientSocket.RemoteEndPoint.ToString().Split(':')[0];
            /*CHANGE 1.2.10 00:14*/
            lock (unAuthenticatedIps)
            {
                if (unAuthenticatedIps.ContainsKey(ip))
                    unAuthenticatedIps.Remove(ip);
            }
            lock (UsersOnline)
            {
                foreach (string key in UsersOnline.Keys)
                    if (UsersOnline[key].Equals(e.ClientSocket))
                    {
                        Utility.Log.Write("UserLog.log", key + " Logged Out From Ip " + ip);
                        UsersOnline.Remove(key);
                        break;
                    }
            }
            /*CHANGE 1.2.10 00:14*/
        }
        private void OnUserBlocked(Utility.Network.ServerEventArguments e)
        {
            string ip = e.ClientSocket.RemoteEndPoint.ToString().Split(':')[0];
            Utility.Log.Write("UserLog.log", "Blocked For Illegal Access From Ip " + ip);
        }
        public void Send(Stream dataStream)
        {
            foreach (string key in UsersOnline.Keys)
            {
                try
                {
                    server.Send(dataStream, UsersOnline[key]);
                }
                catch (Exception) { }
            }
        }
        public void Send(Stream dataStream, Socket client)
        {
            try
            {
                server.Send(dataStream, client);
            }
            catch (Exception) { }
        }
        /*changed*/
        public bool AddUser(string userId, Socket socket)
        {
            if (UsersOnline.ContainsKey(userId)) return false;
            UsersOnline.Add(userId, null);
            return true;
        }
        public void RemoveUser(string userId)
        {
            if (!UsersOnline.ContainsKey(userId) || UsersOnline[userId] != null) return;
            UsersOnline.Remove(userId);
        }
    }
}


现在我不确定我是否正确使用了锁。请给我一些建议。
谢谢。

最佳答案

我猜你读的东西比写的要多吗?如果是这样,ReaderWriterLockSlim可能更适合于减少阻塞(仅在需要检查密钥时进行读取,而对数据进行操作则进行写入)。

我的意思是,您可以先对读取进行双重检查锁定,然后如果失败,则进行写入锁定,再次检查并在必要时添加。

同样-lock(this)通常被皱眉;具有单独的锁定对象是首选。

注意,要生效,所有访问都必须遵守锁;例如,有些地方UsersOnline被锁定,而有些地方没有锁也可以访问它。第二种情况可能会在糊涂中爆炸。

例如:

if (!UsersOnline.ContainsKey(u.GetUserId()))
{
    if (User.ValidateUser(u.GetUserId(), u.GetPassword(), con))
    {
        /*CHANGE 1.2.10 00:14*/
        lock (UsersOnline)
        {
            UsersOnline.Add(u.GetUserId(), e.ClientSocket);


在上面的代码中,如果有两个线程正在查看UsersOnline,则尝试通过不带锁的ContainsKey已经失败了。如果执行此操作时另一个线程正在改变状态。

关于c# - C#-混淆锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2173035/

10-09 00:21