簡體   English   中英

在這種情況下,是否適合進行無鎖設計?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM