简体   繁体   English

在这种情况下,是否适合进行无锁设计?

[英]Is it a reasonable approach for lock-free design for this scenario

This is kind of follow up to one of my earlier question here . 这是我在此之前提出的一个问题的跟进。 In summary I am trying to come up with a lock free design for this scenario where I upon cancellation of task I want to call a method of third party library. 总之,在这种情况下,我想提出一种无锁设计,在这种情况下,我在取消任务后想调用第三方库的方法。 In response to my question, a helpful SO participant suggested to use CancellationToken.Register but I am not sure where and how can I use that here. 为了回答我的问题,一个有帮助的SO参与者建议使用CancellationToken.Register,但我不确定在这里和在哪里可以使用它。 Below is code that I come up with. 下面是我想出的代码。 Please let me know if you see any issue with this approach or if there are any better alternatives to solve this problem. 如果您发现此方法有任何问题,或者是否有更好的替代方法可以解决此问题,请告诉我。

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();
            }
        }
    }

Your process code can be simplified to the following (here is how you use Register) 您的过程代码可以简化为以下内容(这是注册的使用方式)

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.
}

If the token is canceled while within the scope of the using statement it will call library.Clean() if it is called afterwards it does not call the function. 如果令牌在using语句范围内被取消,它将调用library.Clean()如果之后被调用,则不调用该函数。 I also got rid of your Task.Run , there is no reason to waste the extra thread for what you are doing. 我也摆脱了您的Task.Run ,没有理由浪费多余的线程做您的工作。 Lastly I got rid of the extra if (token.IsCancellationRequested) checks, ThrowIfCancellationRequested() has that if check inside of itself, you don't need to check beforehand. 最后,我摆脱了额外的if (token.IsCancellationRequested)检查, ThrowIfCancellationRequested()拥有如果在其内部进行检查,则无需事先检查。

Also, because in my simplification you are not returning tasks anymore your StartProcessing code becomes 另外,由于我的简化,您不再返回任务,因此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
    }

using ForAll( instead of Select( 使用ForAll(而不是Select(

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM