锁定用户线程

3

我需要一种方法来按用户锁定c#线程。

我有我的数据对象,并为每个用户创建一个新实例。 每个用户都有几个线程使用此对象,在I.O操作中,我想仅为此用户锁定此对象实例。 使用简单的Lock{}会锁定所有对象实例,因此阻止其他用户。

我需要一些简单的解决方案。

编辑

我为每个用户构建MyDataObj的新实例; 然后运行更新MyDataObj中某些数据的作业,每分钟一次; 使用lockObj作为锁,将数据锁定到所有用户(尽管它不是静态变量) 我只需要将数据锁定到当前用户

以下是代码示例

public sealed class MyDataObj
{
    private static readonly Dictionary<object, MyDataObj> _instances = new Dictionary<object, MyDataObj>();
    public object lockObj = new object();
    public bool jobRunning = false;
    private string data = string.Empty;
    //// --------- constractor -------------------
    private MyDataObj(int key)
    {
        LoadMyDataObj(key);
    }

    public static MyDataObj GetInstance(int key)
    {
        lock (_instances)
        {
            MyDataObj instance;
            if (_instances.TryGetValue(key, out instance))
            {
                instance = _instances[key];
                return instance;
            }
            instance = new MyDataObj(key);
            return instance;
        }
    }

    private void LoadMyDataObj(int key)
    {
        // get the data from db

    }


    public void UpdateMyData(string newData)
    {
        lock (lockObj)
        {
            this.data = newData;
        }
    }
    public string ReadMyData()
    {
        lock (lockObj)
        {
            return this.data;
        }
    }



    public class ActionObject
    {
        MyDataObj myDataObj;
        int UserID;
        //// --------- constractor -------------------
        public ActionObject(int userid)
        {
            this.UserID = userid;
            myDataObj = MyDataObj.GetInstance(userid);
            if (!myDataObj.jobRunning)
            {
                jobs jbs = new jobs(myDataObj);
                System.Threading.Thread RunJob = new System.Threading.Thread(new System.Threading.ThreadStart(jbs.dominutesAssignment));
                RunJob.Start();
                myDataObj.jobRunning = true;
            }
        }
        public ActionObject()
        {
            myDataObj = MyDataObj.GetInstance(this.UserID);
            myDataObj.UpdateMyData("some data");
        }
    }


    public class jobs
    {
        MyDataObj myDataObj = null;

        public jobs(MyDataObj grp)
        {
            this.myDataObj = grp;
        }
        public void dominutesAssignment()
        {
            while (true)
            {
                myDataObj.ReadMyData();
                System.Threading.Thread.Sleep(1000);
            }
        }
    }
}

3
这里的“lock”一词是什么意思? - Jim Mischel
2
你能发布一下你当前的锁定代码吗? - Ravi Y
你的代码非常混乱。MyDataObj 类包含一个静态字典,其中存储了 MyDataObj 实例和访问它的方法,实例方法和属性只能在内部访问,还有一些嵌套类可以访问 MyDataObj 方法。如果我的同事或员工要求我帮忙调试这个代码,我会建议他首先重构它。目前来看,很难弄清楚谁可以访问什么,以及所有不同部分之间的交互方式。 - Jim Mischel
谢谢Jim的回复。我使用多例模式。(静态字典的目的是确保每个用户都可以访问他自己的MyDataObj实例,这就是为什么MyDataObj有私有构造函数)。ActionObject做两件事:1)启动使用MyDataObj的作业,2)对MyDataobj执行一些操作。我只需要防止作业在同一用户时中断ActionObject。 - gil adino
2个回答

4
我需要一种按用户锁定C#线程的方法。我有我的数据对象,并为每个用户创建新实例。
为每个用户创建一个锁。或者如果用户的存在时间比线程长:使用用户对象作为锁。
lock (userOrTheUserObject)
{
    //Do some op
}

每个用户都有多个线程使用此对象,并进行I.O.操作。

这听起来更像是应该使用异步IO而不是创建多个线程(这样效率会更低)。

我想仅为该用户锁定此对象实例。使用简单的Lock {}会锁定所有对象实例,从而阻止其他用户。

如果对象在所有用户之间共享,则必须使用lock对其进行锁定。否则,锁定将不会非常有效。另一种方法是重新设计对象以不再共享。

我需要一些简单的解决方案。

没有简单的线程解决方案。


3
你可以使用监视器。在这个示例中,除了用户1以外的任何人都可以同时执行DoIt方法。当用户1执行DoIt时,没有人可以进入它。一个弱点是如果用户1尝试在用户2已经执行它时执行DoIt,那么用户2将继续执行它。此外,你必须正确处理异常,否则可能会出现死锁。
private static readonly object lockObj = new Object();

public void Do(int userId)
{
     Monitor.Enter(lockObj);

     if (userId != 1)
          Monitor.Exit(lockObj);

     try
     {
        DoIt();
     }
     finally 
     {
         if (userId == 1)
             Monitor.Exit(lockObj);
     }
}

public void DoIt()
{
    // Do It
}

哇 - 这段代码让我想起了 tryfinally 的必要性。如果 DoIt() 抛出异常会怎样呢?锁将保持,导致死锁情况。另外:为什么不在这里简单地使用 lock () 呢(实际上,这将解决 tryfinally 的问题)? - user57508
事实是:如果您使用lock(),就不会有简单死锁场景的机会。 - user57508
因为他想根据用户动态地更改锁定范围,而我找不到使用 lock 实现它的方法。 - Mehmet Ataş
你可以试试...如果/否则的话,怎么样 :) - user57508
无论如何:http://msdn.microsoft.com/de-de/library/vstudio/de0542zz.aspx 使用C#的try…finally块(Visual Basic中的Try…Finally)来确保释放监视器,或者使用C#的lock语句(Visual Basic中的SyncLock语句),它将Enter和Exit方法包装在try…finally块中。- 我会添加这个摘录 :) - user57508
谢谢你的回答,我需要它能够适用于多个用户,因此我需要管理当前锁定对象的用户。 - gil adino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接