更新 Parallel.ForEach 线程中对象的属性是否安全?

Dav*_*vid 0 c# multithreading thread-safety .net-5

Public Class Customer
{
   public int CustomerId{get;set;}
   Public string CustomerName{get;set;}
}

public class RunParallel(List<Customer> namelessCustomers)
{
   Parallel.ForEach(namelessCustomers, (customer) =>{
      var customerName = CallAPIToReturnCustomerName(customer.CustomerId);
      customer.CustomerName = customerName
   }
}
Run Code Online (Sandbox Code Playgroud)

嗨是customer.CustomerName=customerName线程安全的。我想要的是更新客户列表,以便每个对象都获得客户名称。如果不是,我怎么能得到这样的工作。另外你能解释一下为什么这不是线程安全的吗?

AAA*_*ddd 5

首先,字符串不可变的,引用是原子的,所以属性是线程安全的,这并不是说它不受陈旧值和数据竞争的影响——尽管这里似乎不是这种情况

其次,你调用一个IO工作量parallel.ForEach这是不是最佳的。这意味着,您正在阻塞和占用线程池线程,这些线程可以有效地卸载到 IO 完成端口。您可能最好让 API 调用成为async,并使用Task.WhenAll

例子

public async Task<Customer> CallAPIToReturnCustomerNameAsync(int customerId) 
{
   ///await someThingAsyncHere();
}

...

async Task Process(Customer customer)
{
    customer.CustomerName = await CallAPIToReturnCustomerNameAsync(customer.CustomerId);
}

var tasks = namelessCustomers.Select(Process);
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)