Mã của tôi vẫn ổn nhưng tôi muốn biết phong cách nào tốt hơn và bạn nghĩ sao, tôi đang thử các phương pháp không đồng bộ.
Hãy để tôi thiết lập bối cảnh:
Parallel.ForEach(xmlAnimalList, async xml =>
{
taskList.Add(đang chờ Task.FromResult(ReadAnimalXML(xml, token)));
});
Mã này hoạt động tốt khi sử dụng phương pháp này:
tác vụ không đồng bộ công khai ReadAnimalXML(tên tệp chuỗi, mã thông báo CancellationToken)
Trong ví dụ trước, bạn có thể thấy sau từ khóa chờ đợi Nhiệm vụ.FromResult(). Phương thức ReadAnimalXML chỉ trả về một:
trả về Động vật mới();
Ví dụ thứ hai là thế này:
Parallel.ForEach(xmlAnimalList, async xml =>
{
taskList.Add(đang chờ ReadAnimalXML2(xml, token));
});
Lần này phương thức ReadAnimalXML2 trả về kết quả sau:
tác vụ không đồng bộ công khai<>> ReadAnimalXML2(tên tệp chuỗi, mã thông báo CancellationToken)
{
trả về Task.FromResult(new Animal());
}
Nhưng!
Phương thức thứ hai ReadAnimalXML2 (mà tôi thấy lạ) trả về một
Nhiệm vụ<động vật="">>
động>
Một nhiệm vụ trong một nhiệm vụ.
đây là những gì tôi trở lại Task.FromResult(new Animal()); lý doNếu không nó sẽ không hoạt động đúng. Cả hai phương pháp đều tốt, nhưng một phương pháp tốt hơn.Bạn có thể chia sẻ câu trả lời của bạn và giải thích tại sao?
Cảm ơn bạn đã kiểm tra. Viết mã thật thú vị!
tác vụ không đồng bộ công khai<>> ReadXMLFromFolderAsync(chuỗi folderPath, mã thông báo CancellationToken)
{
if (!Directory.Exists(folderPath))
{
trả về Danh sách mới();
}
Danh sách<>> taskList = Danh sách mới<>>();
Danh sách xmlAnimalList = Directory.GetFiles(folderPath, "*.xml").ToList();
Parallel.ForEach(xmlAnimalList, async xml =>
{
taskList.Add(đang chờ Task.FromResult(ReadAnimalXML(xml, token)));
});
trở lại đang chờ Task.WhenAll(taskList);
}
tác vụ không đồng bộ công khai ReadAnimalXML(tên tệp chuỗi, mã thông báo CancellationToken)
{
Tài liệu XDocument = XDocument.Load(tên tệp);
IEnumerable ADN = đang chờ Task.Run(() =>
document.Descendants("ADN"). Where(adn => adn.Name.LocalName == "Khủng long"), mã thông báo);
// điền vào đối tượng động vật
trả về Động vật mới();
}
tác vụ không đồng bộ công khai<>> ReadXMLFromFolderAsync2(string folderPath, CancellationToken token)
{
if (!Directory.Exists(folderPath))
{
trả về Danh sách mới();
}
Danh sách<>> taskList = Danh sách mới<>>();
Danh sách xmlAnimalList = Directory.GetFiles(folderPath, "*.xml").ToList();
Parallel.ForEach(xmlAnimalList, async xml =>
{
taskList.Add(đang chờ ReadAnimalXML2(xml, token));
});
trở lại đang chờ Task.WhenAll(taskList);
}
tác vụ không đồng bộ công khai<>> ReadAnimalXML2(tên tệp chuỗi, mã thông báo CancellationToken)
{
Tài liệu XDocument = XDocument.Load(tên tệp);
IEnumerable ADN = chờ đợi Task.Run(() => tài liệu
.Hậu duệ("ADN")
.Ở đâu(adn => adn
.Tên
.LocalName == "Khủng long")
, mã thông báo);
// điền vào đối tượng động vật
trả về Task.FromResult(new Animal());
}
Tôi nghĩ bạn đang nhầm lẫn giữa tính song song với async và làm sai cả hai.
Nếu phương thức của bạn trả về Nhiệm vụ.FromResult
, thì nó không đồng bộ. Nếu bạn muốn mã không đồng bộ, hãy tập trung vào I/O - ví dụ: thực hiện I/O không đồng bộ để tải dữ liệu tệp từ đĩa và sau đó phân tích cú pháp (đồng bộ) thành XML.
Song song.ForEach
Vấn đề nguy hiểm hơn. Đầu tiên, bạn không thể sử dụng async
sử dụng Song song.ForEach
phương pháp; mã của bạn tình cờ hoạt động vì async
Phương thức không đồng bộ. Ngoài ra, bạn không thể sử dụng các phương pháp không an toàn cho luồng như Danh sách.Thêm
từ mã song song. Hầu như tất cả các mã sử dụng Song song.ForEach
là sai. nhưng có lẽ bạn không cần Song song.ForEach
Dẫu sao thì.
Nếu bạn muốn thực hiện đồng thời không đồng bộ thì bạn chỉ cần LINQSelect
có thể được hòa giải đang chờ đợi Nhiệm vụ.Khi Tất cả
.Nếu bạn muốn thiết lập một đường ống có thể xử lý song song, thì bạn có thể sử dụng TPL Dataflow hoặc sử dụng Song song.ForEach
仅Sử dụng mã đồng bộ sau khi phần không đồng bộ hoàn tất.
Tôi là một lập trình viên xuất sắc, rất giỏi!