【问题标题】:Tasks work with one method. How to prevent code duplication?任务使用一种方法。如何防止代码重复?
【发布时间】:2019-12-26 07:36:30
【问题描述】:

假设有两个任务:

Task.Run(() => {
    while (!this.isCanceled)
        DoOperation(obj);
});

Task.Run(() => {
    foreach(var obj in objects)   // Another objects' subset
        while(!this.isCancelled)
            DoOperation(obj);
});

DoOperation(Foo obj) 实现:

DoOperation(Foo obj)
{
    if (obj.IsBar && obj.IsFoo)
        obj.MakeSad();
    else
        obj.MakeHappy();
}

我们可以锁定方法DoOperation,一切都应该很好,但是这种方法有一些性能负面的方面。此外,使用DoOperation 方法可以一次处理大量任务。 第二种方法是将整个方法复制到每个任务中。但情况更糟。

那么问题是如何避免锁定并防止代码重复?

【问题讨论】:

    标签: c# task code-duplication


    【解决方案1】:

    如果您的操作,关键代码是什么?必须有一个或多个竞争条件,否则根本不需要使用锁。

    如果在您的示例中它是 DoSomething 中的内容,则使用那里的锁:

    DoOperation(Foo obj)
    {
        if (obj.IsBar && obj.IsFoo)
            obj.MakeSad();
        else {
            lock(lockObject1) {
                 obj.MakeHappy();
            }
        }
    }
    

    这样,如果功能在没有被阻塞的情况下工作,您就不会复制代码和其他所有内容。如果使用了另一个有争议的块,请使用另一个锁对象,这样它们就不会相互阻塞。

    顺便说一句,由于您正在使用任务和同步编程,最好用户SemaphoreSlim锁定https://blog.cdemi.io/async-waiting-inside-c-sharp-locks/amp/

    【讨论】:

    • DoSomething 方法没有问题,因为它处理不同的Foo 对象,但我认为这种方法在调用不同任务的不同对象时仍然会出现一些问题是否可能,例如,要调用obj.MakeHappy(),其中堆栈中的 obj 地址类似于不同引用上的 0x04a1(obj 地址为 0x9a2c)处理多个任务?
    猜你喜欢
    • 1970-01-01
    • 2017-09-25
    • 2021-03-25
    • 1970-01-01
    • 2020-12-26
    • 2015-03-02
    • 2017-05-07
    • 2020-10-02
    • 2019-01-25
    相关资源
    最近更新 更多