需要知道我的线程锁是否在.Net中应该做到了什么?

时间:2010-08-17 15:45:56

标签: c# .net multithreading .net-3.5

我有一个应用程序,在创建一个线程之前,它调用数据库来提取X条记录。从数据库中检索记录时,将设置锁定标志,以便不再拉动这些记录。

一旦线程完成,它将从该数据库中提取更多记录。当我从一个线程调用数据库时,我应该对该段代码设置一个锁定,以便当时只有那个线程调用它?这是我的代码的例子(我在我有锁的区域评论过):

private void CreateThreads() 
{ 
       for(var i = 1; i <= _threadCount; i++) 
    { 
        var adapter = new Dystopia.DataAdapter(); 
        var records = adapter.FindAllWithLocking(_recordsPerThread,_validationId,_validationDateTime); 
        if(records != null && records.Count > 0) 
        { 
            var paramss = new ArrayList { i, records }; 
            ThreadPool.QueueUserWorkItem(ThreadWorker, paramss);
        } 

        this.Update(); 
    } 


} 

private void ThreadWorker(object paramList) 
{ 
    try 
    { 
        var parms = (ArrayList) paramList; 
        var stopThread = false; 
        var threadCount = (int) parms[0]; 
        var records = (List<Candidates>) parms[1]; 
        var runOnce = false; 
        var adapter = new Dystopia.DataAdapter(); 
        var lastCount = records.Count; 
        var runningCount = 0; 
        while (_stopThreads == false) 
        { 


           if (records.Count > 0) 
            { 
                foreach (var record in records) 
                { 
                    var proc = new ProcRecords(); 
                    proc.Validate(ref rec); 


                    adapter.Update(rec);

                    if (_stopThreads) 
                    { 
                        break; 
                    } 
                } 
                //This is where I think I may need to sync the threads.
                //Is this correct?
                lock(this){
                records = adapter.FindAllWithLocking;  
                }             
            } 
        } 
    } 
    catch (Exception ex) 
    { 
        MessageBox.Show(ex.Message); 
    } 

SQL to Pull记录:

WITH cte AS ( 
  SELECT TOP (@topCount) *
  FROM Candidates WITH (READPAST) 
  WHERE 
  isLocked = 0 and
  isTested = 0 and  
  validated = 0 
  ) 
UPDATE cte 
  SET 
  isLocked = 1,
  validationID = @validationId,
  validationDateTime = @validationDateTime
  OUTPUT INSERTED.*;

3 个答案:

答案 0 :(得分:2)

您不需要锁定线程,因为数据库应该根据您的请求执行此操作。

答案 1 :(得分:1)

我看到了一些问题。

首先,您正在测试_stopThreads == false,但您尚未透露这是否是一个易变的读取。阅读answer的一半中的第二个,以便对我所谈论的内容有一个很好的描述。

其次,锁是没有意义的,因为adapter是对非共享对象的本地引用,而records是一个刚被替换的本地引用。我假设适配器与数据库建立了单独的连接,但如果它共享现有连接,则可能需要进行某种类型的同步,因为ADO.NET连接对象通常不是线程安全的。

现在,您可能需要在某处锁定以发布工作项的结果。我没有看到结果发布到主线程的位置,所以我不能在这里提供任何指导。

顺便说一下,我会避免在ThreadPool帖子中显示一个消息框。原因是这将挂起该线程,直到消息框关闭。

答案 2 :(得分:0)

你不应该锁定(这个),因为你很容易创建死锁,你应该创建一个单独的锁对象。如果您搜索“锁定(此)”,您可以找到许多关于原因的文章。

这是关于lock(this)

的SO问题