c#并行播种statirandom.为了得到一个可重复的序列

本文关键字:一个 并行 statirandom | 更新日期: 2023-09-27 18:02:14

我正在做一个c#项目,需要并行的随机数。for循环。为此,我使用了Jon Skeet的MiscUtil中的statirandom类。

对于测试,我希望能够重现我的结果。因此,我试着播种底层系统。每次测试运行时随机获得相同的序列。然而,即使有了种子,我每次都会得到不同的结果。在常规的for循环中,每次都输出相同的序列。下面的代码可以重现我的问题(你必须用你的机器的输出来更新预期的序列)。

是否有一种方法来播种随机,这样我就可以在并行中获得可重复的序列。for循环?

    [TestMethod]
    public void MultiThreadedSeededRandom()
    {
        var actual = new ConcurrentBag<int>();
        Parallel.For(0, 10, i =>
        {
            actual.Add(StaticRandom.Next(1000));
        });
        WriteActualToOutput(actual);
        var expected = new int[] { 743, 51, 847, 682, 368, 959, 245, 849, 192, 440, };
        Assert.IsTrue(AreEqual(expected, actual.ToArray()));
    }
    public static bool AreEqual<T>(T[] expected, T[] actual)
    {
        if (expected.Length != actual.Length)
            return false;
        for (int i = 0; i < expected.Length; i++)
        {
            if (!expected[i].Equals(actual[i]))
                return false;
        }
        return true;
    }
    private static void WriteActualToOutput(ConcurrentBag<int> acual)
    {
        var result = string.Empty;
        result += "new int[] {";
        foreach (var value in acual)
        {
            result += value.ToString() + ",";
        }
        result += "};";
        Trace.WriteLine(result);
    }
    public static class StaticRandom
    {
        private static Random random = new Random(1231241);
        private static object myLock = new object();
        public static int Next(int max)
        {
            object obj;
            Monitor.Enter(obj = StaticRandom.myLock);
            int result;
            try
            {
                result = StaticRandom.random.Next(max);
            }
            finally
            {
                Monitor.Exit(obj);
            }
            return result;
        }
    }

c#并行播种statirandom.为了得到一个可重复的序列

当您使用Parallel.For时,根据设计,您将获得顺序之外的结果,因为每个迭代将以不确定的方式并行运行。如果您需要相同的"随机"数字序列,则需要以可靠的顺序调用Random.Next()。这在多个线程中不起作用。

您不应该尝试使用Parallel.For填充随机数,而应该考虑提前生成"随机数"序列,然后在事后使用Parallel.For根据这些数字进行处理。这样,您将始终以正确的顺序生成数字,这将保持顺序。

另外,如果你从未使用过StringBuilder,你可以在你的Output方法中使用它的效率:

private static void WriteToArrayString(ICollection items)
    {
        var result = new StringBuilder("new []{");
        var index = 0;
        foreach(var value in items)
        {
            if (index == (items.Count - 1))
            {
                result.Append(string.Concat(value));
                index++;
                continue;
            }
            result.Append(string.Concat(value, ','));
            index++;
        }
        result.Append("};");
        Trace.WriteLine(result.ToString());
    }