0

我有一个具有并行线程计时器的程序。基本上,这些计时器设置为每 10 秒运行一次方法。在该方法中,线程在列表上获得锁定以制作副本以完成工作。

private object access = new object();
PeriodTask(){
    lock(access){
        copy = list.Where(e => e.valid).toList();
    }
    foreach (var element in copy)
        do some not so quick work.
}

我还有一种方法可以获取有关那些也要求锁定的元素的信息。并得到一份

informationMethod(){
    lock(access){
        return list.Select(element => new serializableElement(element)).toList()

    }
}

我需要锁的原因是因为有一些方法可以从这个列表中添加和删除项目,也可以锁定它。但我什至还没有给他们打电话。

我遇到的问题是信息检索方法在此类的实例之间阻塞或休眠很长时间。其中可能有大约 10 个,并且似乎一次可以访问 2 或 3 个,但该过程可能需要一分半到两分钟才能获得所有这些。我提到的第一个在计时器上执行的方法在应该的时候可以很好地访问并立即释放锁,但是即使它是执行的主线程,另一个也很难执行。

我有几个测试实例化这些类的管理器。

//sets up updaters test
var manager = new manager(config);
Assert.IsNotNull(manager);
Assert.IsFalse(manager.UpdatersRunning);
Assert.AreNotEqual(0, manager.Updaters.Count());//calls the informationMethod on each updater
manager.Dispose();
//This test doesn't even run the period task


//Waits to start updaters test
var manager = new StatusObjectManager(config);
Assert.IsNotNull(manager);
Assert.AreNotEqual(0, manager.Updaters.Count());
Assert.IsFalse(manager.UpdatersRunning);
Assert.AreEqual(0, manager.Updaters.Count(u => u.Running));
manager.StartUpdaters();
Assert.IsTrue(manager.UpdatersRunning);
Assert.AreNotEqual(0, manager.Updaters.Count(u => u.Running));
manager.Dispose();
//This test runs the period tasks and checks to make sure their running. Or at least 1.
//THis test takes a long time for the first informationMethod bout but not the other 2.

The code in the manager looks like this
return updaters.select(u => new serialUpdater(su));

此时不需要锁定,因为该列表没有被修改。

有没有人知道会发生什么。我不知道如何判断线程是在锁上阻塞还是只是休眠了异常的时间。

4

1 回答 1

0

这里的第一步是添加日志记录。简单Trace.WriteLine的在锁之前和内部,您还可以Thread.CurrentThread.Name在创建时获取/设置,读取 aThread这样您就可以知道哪个Thread在方法中。

下一步将是实现一些不那么干净但更快的东西,例如System.Threading.ReaderWriterLockSlim。这样做的好处是,它将允许所有线程同时读取,但在写入时阻止所有内容。所以本质上你只是在写一个阻塞。

ToList另外,在执行orToArray等​​操作时要注意引用类型。

void Main()
{
    var slist = new List<Chunk>();
    var chunk = new Chunk{Name="asdf"};
    slist.Add(chunk);
    var slist2 = slist.ToList();
    slist[0].Name = "asdf2";
    Console.WriteLine(slist[0].Name); // outputs: asdf2
    Console.WriteLine(slist2[0].Name); // outputs: asdf2
}

public class Chunk
{
    public string Name {get;set;}
}
于 2013-08-14T21:04:47.000 回答