[英]Is it a reasonable approach for lock-free design for this scenario
這是我在此之前提出的一個問題的跟進。 總之,在這種情況下,我想提出一種無鎖設計,在這種情況下,我在取消任務后想調用第三方庫的方法。 為了回答我的問題,一個有幫助的SO參與者建議使用CancellationToken.Register,但我不確定在這里和在哪里可以使用它。 下面是我想出的代碼。 如果您發現此方法有任何問題,或者是否有更好的替代方法可以解決此問題,請告訴我。
class ProcessEmployees
{
private List<Employee> _Employees;
CancellationTokenSource cs = new CancellationTokenSource();
public ProcessEmployees()
{
_Employees = new List<Employee>()
{
new Employee() { ID = 1, FirstName = "John", LastName = "Doe" },
new Employee() { ID = 2, FirstName = "Peter", LastName = "Saul" },
new Employee() { ID = 3, FirstName = "Mike", LastName = "Sue" },
new Employee() { ID = 4, FirstName = "Catherina", LastName = "Desoza" },
new Employee() { ID = 5, FirstName = "Paul", LastName = "Smith" }
};
}
public void StartProcessing()
{
try
{
Task[] tasks = this._Employees.AsParallel().WithCancellation(cs.Token).Select(x => this.ProcessThisEmployee(x, cs.Token)).ToArray();
Task.WaitAll(tasks);
}
catch (AggregateException ae)
{
// error handling code
}
// other stuff
}
private async Task ProcessThisEmployee(Employee x, CancellationToken token)
{
ThirdPartyLibrary library = new ThirdPartyLibrary();
if (token.IsCancellationRequested)
token.ThrowIfCancellationRequested();
await Task.Factory.StartNew(() => library.SomeAPI(x) );
if (token.IsCancellationRequested)
{
library.Clean();
token.ThrowIfCancellationRequested();
}
}
}
您的過程代碼可以簡化為以下內容(這是注冊的使用方式)
private void ProcessThisEmployee(Employee x, CancellationToken token)
{
ThirdPartyLibrary library = new ThirdPartyLibrary();
token.ThrowIfCancellationRequested();
using(token.Register(() => library.Clean())
{
library.SomeAPI(x);
}
token.ThrowIfCancellationRequested(); //Not sure why you cancel here in your original example.
}
如果令牌在using
語句范圍內被取消,它將調用library.Clean()
如果之后被調用,則不調用該函數。 我也擺脫了您的Task.Run
,沒有理由浪費多余的線程做您的工作。 最后,我擺脫了額外的if (token.IsCancellationRequested)
檢查, ThrowIfCancellationRequested()
擁有如果在其內部進行檢查,則無需事先檢查。
另外,由於我的簡化,您不再返回任務,因此StartProcessing代碼變為
public void StartProcessing()
{
try
{
this._Employees.AsParallel().WithCancellation(cs.Token).ForAll(x => this.ProcessThisEmployee(x, cs.Token));
}
catch (AggregateException ae)
{
// error handling code
}
// other stuff
}
使用ForAll(
而不是Select(
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.