我需要使用随机类在公共静态函数内的多线程应用程序中生成随机数。我怎样才能实现它。目前,下面的功能运行良好,但与随机类相比,它不是很快。因此,我需要修改下面的函数并使其与随机类一起工作,同时在该类中发生数千个并发调用。如果我使用随机它,我想每次通话使用相同的种子,随机化非常糟糕。 我目前的班级
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
public static class GenerateRandomValue
{
static RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
public static int GenerateRandomValueDefault(int irRandValRange)//default min val 1
{
if (irRandValRange == 0)
irRandValRange = 1;
byte[] randomNumber = new byte[4]; // 4 bytes per Int32
Gen.GetBytes(randomNumber);
return Math.Abs(BitConverter.ToInt32(randomNumber, 0) % irRandValRange) + 1;
}
public static int GenerateRandomValueMin(int irRandValRange, int irMinValue)
{
byte[] randomNumber = new byte[4]; // 4 bytes per Int32
Gen.GetBytes(randomNumber);
return BitConverter.ToInt32(randomNumber, 0) % irRandValRange + irMinValue;
}
}
另一个看起来非常好且线程安全的功能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
public static class GenerateRandomValue
{
private static Random seedGenerator = new Random();
private static ThreadLocal<Random> random = new ThreadLocal<Random>(SeededRandomFactory);
private static Random SeededRandomFactory()
{
lock(seedGenerator)
return new Random(seedGenerator.Next());
}
public static int GenerateRandomValueMin(int irRandValRange, int irMinValue)
{
return random.Value.Next(irMinValue, irRandValRange);
}
}
答案 0 :(得分:3)
你没有指定除速度之外的任何约束,所以我认为Random
应该这样做。
// Field in the class
Random rand = new Random();
// Inside a method:
int randomValue = rand.Next(); // Random positive integer returned
int randomValue = rand.Next(max); // Random under max
int randomValue = rand.Next(min, max); // Random in range
答案 1 :(得分:3)
您需要的是在ASP.NET应用程序中启动种子设定的更好方法,使用以下方法可以很好地使用Random的质量。
public static int GenerateRandomValueDefault(int irRandValRange)//default min val 1
{
return GenerateRandomValueMin(irRandValRange, 1);
}
public static int GenerateRandomValueMin(int irRandValRange, int irMinValue)
{
Random rand = GetRandom();
return rand.GetNext(irMinValue,irRandValRange)
}
//This is a global random number generator, it is only used to provide the seed for the local RNG's.
private static Random GlobalRandom = new Random();
private static Random GetRandom()
{
if (HttpContext.Current.Session["RNG"] == null)
{
//This lock is only hit the very first time the users Session state is used, every time after that it should use the cached local copy without taking the lock.
lock(GlobalRandom)
{
//We use the Global RNG for seed instead of the default because it uses time to seed by default, and if two people get a new Random() within the same time-slice they will have the same seed. This prevents that from happening.
HttpContext.Current.Session["RNG"] = new Random(GlobalRandom.Next());
}
}
//Return the cached/new RNG.
return (Random)HttpContext.Current.Session["RNG"];
}
您有一个锁定的全局RNG实例,但只有在生成新会话状态时才会触发此事件,之后会话仅使用其本地副本。您将在运行时获得非常好的性能,并且每人的第一页加载会有轻微负载,因为它会从全局存储中生成一个数字。
您可以根据自己的需要对其进行修改,但它会为您提供一般性的想法,但它会为您提供一般的想法。
根据Henk Holterman的建议,这里的解锁方案可能更快,不会使用HttpState。
private static int SeedCounter = 0;
private readonly object SeedInitLock = new Object();
private static Random GetRandom()
{
//Do init the first time this function is ever called.
if(SeedCounter == -1)
{
//The first time the function is called everyone will try to update SeedCounter, but only the first
//thread to complete it will be the value everyone uses.
Random initRNG = new Random();
Interlocked.CompareExchange(ref SeedCounter, initRNG.Next(), -1);
}
else if (SeedCounter < 0)
{
//Because Interlocked.Increment wraps the value to int.MinValue and Random(int) will take the absolute
//value of the seed, we skip all of the negitive numbers and go to 0.
Interlocked.CompareExchange(ref SeedCounter, 0, int.MinValue);
}
int tempSeed = Interlocked.Increment(ref SeedCounter);
if (tempSeed < 0)
{
//If tempSeed is negative we hit a edge case where SeedCounter wrapped around. We just call the function
//again so we do not reuse a seed that was just used.
return GetRandom();
}
return new Random(tempSeed);
}
答案 2 :(得分:0)
我建议使用System.Web.Security.Membership.GeneratePassword()
方法。
string generated = System.Web.Security.Membership.GeneratePassword(
10, // maximum length
3) // number of non-ASCII characters.
答案 3 :(得分:0)
使用随机优质种子被认为是“表现明智”更好。但是你需要表现吗?
在此博客中查看指标:http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx 最后有关提供者播种的提示。
尽管带着一粒盐。你必须重做测试才能确定。