c# - 将 .NET 4 线程转换为 .NET 2

标签 c# .net multithreading unity3d game-physics

我正在使用其他人的 .NET 4 开源平滑粒子流体动力学代码,我正在尝试将其转换为 Unity 项目,您只能指望它达到 .NET 2 标准。不幸的是,代码使用了 Parallels 类(这太棒了!),但他使用了一个更晦涩的重载。有谁能找到一种在 .NET 2 中实现相同目标而又不会对性能造成巨大影响的好方法吗?

    Parallel.For(
        0,
        _numActiveParticles,
        () => new Vector2[MAX_PARTICLES],
        (i, state, accumulatedDelta) => calculateForce(_activeParticles[i], accumulatedDelta),
        (accumulatedDelta) =>
        {
            lock (_calculateForcesLock)
            {
                for (int i = _numActiveParticles - 1; i >= 0; i--)
                {
                    int index = _activeParticles[i];
                    _delta[index] += accumulatedDelta[index] / MULTIPLIER;
                }
            }
        }
    );

认为这就是代码的作用(非线程):

    for (int i = 0; i < _numActiveParticles; i++)
    {
        Vector2[] temp = new Vector2[MAX_PARTICLES];
        temp = calculateForce(_activeParticles[i], temp);


        for (int k = _numActiveParticles - 1; k >= 0; k--)
        {
            int index = _activeParticles[k];
            _delta[index] += temp[index] / MULTIPLIER;
        }
    }

最佳答案

您的第二个代码不正确。我认为正确的代码是这样的:

var accumulatedDelta= new Vector2[MAX_PARTICLES];

for(int i = 0; i < _numActiveParticles; ++i)
{
    accumulatedDelta = calculateForce(_activeParticles[i], accumulatedDelta);
}

for (int i = _numActiveParticles - 1; i >= 0; i--)
{
    int index = _activeParticles[i];
    _delta[index] += accumulatedDelta[index] / MULTIPLIER;
}

我不知道 .net2 有什么,没有什么。但是您可以自己模拟 Parallel.For

Parallel.For 重载的解释是这样的:

第一个参数:循环起始索引

第二个参数:循环结束索引

第三个参数:将创建任务本地数据的委托(delegate)。对于 Parallel.For 使用的每个线程(任务),将调用此委托(delegate)并返回 localInit 数据。

第四个参数:作为for主体的委托(delegate)。在 body delegate 的第一次执行中,该委托(delegate)将检索由 previuse delegate (localInit) 创建的数据。在每个后续循环中,主体委托(delegate)可以更改 localInit,然后将其返回给下一个主体执行。在主体委托(delegate)的最后一次执行中,localInit 数据将传递给最后一个委托(delegate)。

最后一个参数:每个任务将调用的另一个委托(delegate),当任务完成它的工作时。 localInit 将传递给此委托(delegate)。因为这个委托(delegate)可以被多个任务调用并发,所以你必须保护你的共享数据。

编辑:

ParallelFor 的一个版本可以是这样的:

public static void ParallerFor<TLocal>(int startIndex, int endIndex, Func<TLocal> initData, Func<int, TLocal, TLocal> body, Action<TLocal> finalizer)
    {
        int numThreads = Environment.ProcessorCount;
        int chunkOffset = ((endIndex - startIndex) / numThreads) + 1;

        Task[] tasks = new Task[numThreads];

        Enumerable.Range(0, numThreads).ToList().ForEach(x =>
            {
                int start = x * chunkOffset;
                int end = ((x + 1) * chunkOffset);
                end = end > endIndex ? endIndex : end;

                tasks[x] = Task.Factory.StartNew(() =>
                {
                    TLocal init = initData();

                    for(int i = start; i < end; ++i)
                    {
                        init = body(i, init);
                    }

                    finalizer(init);
                });
            });

        Task.WhenAll(tasks).Wait();
    }

关于c# - 将 .NET 4 线程转换为 .NET 2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20652011/

相关文章:

.net - Web API Swagger 文档导出为 PDF

c# - ViewBag RuntimeBinderException(MVC 4、ASPX)

c# - 如何移动 TrackBar 以响应 C# 中的鼠标事件?

c# - .net 中的任何 p2p 库

c# - ReSharper 重新格式化、数组初始化、逗号后的空格

java - 为什么消费者会降低生产者的绩效

java - CompletableFuture - 并行运行多个 rest 调用并获得不同的结果

c# - 如何从当前执行的方法中获取 BackgroundWorker 的实例?

c# - 模拟 Entity Framework 数据库

c# - 使用 .NET 格式化大数