我的一个学生要求我创建一个解释多线程的例子。我想出了这个伪示例,它将生成线程,这些线程将循环随机次数并在循环时休眠。我通过使用Guid标识每个线程的Dictionary来跟踪这些线程。
字典可以在用于监控这些线程的页面上使用,并可能" kill"它们。
这看起来是否合理:
public class LongProcess
{
public static Dictionary<Guid, LongProcess> Monitor = new Dictionary<Guid, LongProcess>();
public Guid Id { get; set; }
public int Iterations { get; set; }//number of loops
public int SleepFactor { get; set; }//rest period while looping
public int CompletedIterations { get; set; }//number of completed loops
void Process()
{
for(var i = 0 ; i < Iterations; i++)
{
Thread.Sleep(1000*SleepFactor);
SleepFactor = new Random(DateTime.Now.Millisecond).Next(1, 5);
this.CompletedIterations++;
}
}
public void Start()
{
Monitor.Add(Id, this);
var thread = new Thread(new ThreadStart(Process));
thread.Start();
}
}
以下是该课程的使用方法:
var id = Guid.NewGuid();
var rnd = new Random(DateTime.Now.Millisecond);
var process = new LongProcess
{
Iterations = rnd.Next(5, 20),
SleepFactor = rnd.Next(1, 5),
Id = id
};
process.Start();
任何想法都会受到赞赏。
答案 0 :(得分:4)
只要对process.Start
的所有调用都发生在同一个线程上,就不需要锁定字典,因为它不会在LongProcess
内启动的后台线程中访问类。这意味着:您的班级LongProcess
不是线程安全的,但在您当前的代码中,这不是问题
为了安全起见并避免锁定,您可以使用.NET4中的新ConcurrentDictionary<TKey, TValue>
。
答案 1 :(得分:2)
其他人已经回答了字典周围的锁定,我同意他们的看法。
我要改变的一件事是属性上的设置者。它们当前是公共的,这意味着你可以在线程迭代时修改底层值,这不是一个很好的api设计。
我会在类中添加一个构造函数来获取你想要的参数并使setter变为私有,这样就没有人会不小心改变你的类的值,从而导致奇怪的结果。
答案 2 :(得分:0)
您将需要锁定字典,它将被多个线程访问,或者您可以使用System.Collections.Concurrent.ConcurrentDictionary,这是设计线程安全的