C# 这段代码实际上是线程安全的吗?
关于我在微软的C#教程网页上找到的以下代码段,我有一个问题。在代码中,它们提供了任务的演示。在事件处理程序中,它们创建一个更新未受保护集合的任务 这段代码是线程安全的吗?在我看来不是。使此代码线程安全的最佳方法是什么C# 这段代码实际上是线程安全的吗?,c#,multithreading,C#,Multithreading,关于我在微软的C#教程网页上找到的以下代码段,我有一个问题。在代码中,它们提供了任务的演示。在事件处理程序中,它们创建一个更新未受保护集合的任务 这段代码是线程安全的吗?在我看来不是。使此代码线程安全的最佳方法是什么 private ArrayList students = new ArrayList(); private void btnCreateStudent_Click(object sender, RoutedEventArgs e) { Student newStudent
private ArrayList students = new ArrayList();
private void btnCreateStudent_Click(object sender, RoutedEventArgs e)
{
Student newStudent = new Student();
newStudent.FirstName = txtFirstName.Text;
newStudent.LastName = txtLastName.Text;
newStudent.City = txtCity.Text;
ClearForm();
Task task1 = new Task(() => AddToCollection(newStudent));
task1.Start();
ClearForm();
}
private void AddToCollection(Student student)
{
Thread.Sleep(5000);
students.Add(student);
int count = students.Count;
MessageBox.Show("Student created successfully. Collection contains " + count.ToString() + " Student(s).");
}
我不同意下面的说法
students.Add(student);
我认为应该用锁来保护它。“线程安全”在很大程度上取决于您在单独线程之外所做的事情。
如果在任务运行期间,在任务外部不接触学生,则代码是线程安全的
如果在任务的生命周期内在外部使用学生
,则应同步访问。
您可以使用锁
或
当然,您也可以使用一些
这段代码实际上是线程安全的吗
private ArrayList students = new ArrayList();
private void btnCreateStudent_Click(object sender, RoutedEventArgs e)
{
Student newStudent = new Student();
newStudent.FirstName = txtFirstName.Text;
newStudent.LastName = txtLastName.Text;
newStudent.City = txtCity.Text;
ClearForm();
Task task1 = new Task(() => AddToCollection(newStudent));
task1.Start();
ClearForm();
}
private void AddToCollection(Student student)
{
Thread.Sleep(5000);
students.Add(student);
int count = students.Count;
MessageBox.Show("Student created successfully. Collection contains " + count.ToString() + " Student(s).");
}
不,不是
根据定义,ArrayList
实例不支持并发修改,除非它是通过Synchronized
方法返回的,而这里不是这种情况
虽然这可能并不明显,但在您的示例中可能会发生并发修改。任务
排队到线程池
,它将由该池中的某个线程运行。如果用户双击btnCreateStudent
将创建两个任务,并且由于Thread.Sleep
不是很精确,而且无论如何,任务不必立即执行(例如线程池队列可能已满),因此两个任务虽然在不同的时间安排,但可以同时执行
使此代码线程安全的最佳方法是什么
private ArrayList students = new ArrayList();
private void btnCreateStudent_Click(object sender, RoutedEventArgs e)
{
Student newStudent = new Student();
newStudent.FirstName = txtFirstName.Text;
newStudent.LastName = txtLastName.Text;
newStudent.City = txtCity.Text;
ClearForm();
Task task1 = new Task(() => AddToCollection(newStudent));
task1.Start();
ClearForm();
}
private void AddToCollection(Student student)
{
Thread.Sleep(5000);
students.Add(student);
int count = students.Count;
MessageBox.Show("Student created successfully. Collection contains " + count.ToString() + " Student(s).");
}
这取决于你所说的“最好”是什么意思
第一种解决方案是使用该方法创建ArrayList
但您仍然必须使用锁来枚举此列表
通过集合枚举本质上不是线程安全的
程序即使在同步集合时,其他线程也可以
仍然修改集合,这会导致枚举数抛出
例外。要保证枚举期间的线程安全,可以
在整个枚举过程中锁定集合或捕获
由其他线程所做的更改导致的异常
另一种解决方案是在访问集合的任何位置使用和添加锁。List
优于ArrayList
,因为它包含元素类型,所以不必在读取时强制转换它们,也不会意外地将不兼容的类型添加到集合中
如果您不关心项目的顺序,那么您应该使用,它不需要任何锁定。您的意思是线程安全?您是在哪个MSDN页面上这样做的?您特别想知道什么是线程安全的?添加呼叫?实际上,我不确定这段代码是否能正常工作,因为您正在任务中调用MessageBox.Show。这些应该在UI线程上运行。我发现了一个更为复杂的代码,不是MSDNDon't use
ArrayList
,它是泛型退出前1.1天从.NET遗留下来的。您应该改为使用List
。MessageBox.Show()是一个线程安全调用(因为它是静态的)。ArrayList.Add()不是。我定期调用该任务。每次鼠标单击将创建一个单独的踏板。什么会导致许多竞争对手threads@DavidYachnis然后你需要一个同步。