异步随机字母生成太快
本文关键字:随机 异步 | 更新日期: 2023-09-27 18:07:07
我知道生成器有一个问题,因为它们有时太快,最终生成相同的字符两次,或者根本不生成。我正在创建一个生成随机字符的程序,我想包含一个进度条,我打算使用异步生成来实现它。
问题是它不能正确生成,因为它生成得太快了。我让它生成3组字符它会生成1组,或者5组字符它会生成2组
我如何减慢它并允许它异步生成,或者我如何以其他方式实现一个工作进度条?
下面是我的一些代码:
private void btnGenerate_Click(object sender, EventArgs e) {
Random rand = new Random();
string result;
bool failed = false;
int amount = Convert.ToInt32(numMassGen.Value),
initialAmount = amount;
while(0 < amount--) {
result = Generate(rand).Result;
if(result != "failed") {
WriteToFile(result, initialAmount - amount);
statusText.Text = "Finished generating and saving " + (initialAmount - amount) + "/" + initialAmount + " keys.";
}
else {
UpdateStatus("Not enough options selected for this length.");
failed = true;
break;
}
}
if(!failed) {
UpdateStatus("Finished generating and saving " + numMassGen.Value + " keys.");
}
}
private Task WriteToFile(string result, int completed) {
return WriteToFileAsync(result);
}
private async Task WriteToFileAsync(string result) {
byte[] resultEncoded = Encoding.UTF8.GetBytes(result + Environment.NewLine);
using(FileStream stream = new FileStream(txtSaveLocation.Text,
FileMode.Append,
FileAccess.Write,
FileShare.None,
bufferSize: 4096,
useAsync: true)) {
await stream.WriteAsync(resultEncoded, 0, resultEncoded.Length);
}
}
// This method's probably crude, it's a little old and I don't know
// how to improve it.
// This is also where the problems occur. When I step through this code,
// it's slowing down the random generation.
// When I run it normally, it's too fast and skips generating.
private async Task<string> GenerateAsync(Random rand) {
string sAll = "", result = "", sLower, sUpper, sNumbers, sHyphen, sUnderscore, sSpace, sSpecial, sBrackets;
int length = Convert.ToInt32(numSections.Value) * Convert.ToInt32(numCharacters.Value),
initialLength = length;
char character;
sLower = "abcdefghijklmnopqrstuvwxyz";
sUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
sNumbers = "0123456789";
sHyphen = "-";
sUnderscore = "_";
sSpace = " ";
sSpecial = "`~!@#$%^&*()+=''|/?.,;:''"";
sBrackets = "()[]{}<>";
if(Properties.Settings.Default.charUppercase)
sAll += sUpper;
if(Properties.Settings.Default.charLowercase)
sAll += sLower;
if(Properties.Settings.Default.charNumbers)
sAll += sNumbers;
if(Properties.Settings.Default.charUnderscore)
sAll += sUnderscore;
if(Properties.Settings.Default.charSpace)
sAll += sSpace;
if(Properties.Settings.Default.charSpecial)
sAll += sSpecial;
if(Properties.Settings.Default.charBrackets)
sAll += sBrackets;
while(0 < length) {
if(sAll.Length == 0) {
return "failed";
}
character = sAll[rand.Next(sAll.Length)];
if(Properties.Settings.Default.charRepeat) {
sAll = sAll.Remove(sAll.IndexOf(character), 1);
}
if((length % Properties.Settings.Default.secCharacters == 0) && (length != 0) && (length != initialLength)) {
result += sHyphen;
}
result += character;
length--;
}
return result;
}
从你的评论
为什么我随机生成的字符有时会连续出现两次,有些回答说这是因为这个过程运行得太快了,需要时间来生成另一个字符。
如果您在短时间内创建Random
类的新实例并从中请求新值(很可能是在循环中),则通常会发生这种情况。在这种情况下,每个新的Random
对象可能从当前系统时钟获得相同的种子,并可能产生相同的伪随机数。这就是大多数伪随机生成器的设计工作方式。
Random
类的相同实例 (这是您应该做的),这是不可能的(有一个注意事项,见下文)。这是由于Random
类能够考虑到其先前的状态。
注意,random不等于unique。
伪随机数生成器绝对有可能产生相同数字的序列。例如,如果您只有0或1的选择,RNG 可能产生只包含0的序列:0, 0, 0, 0, 0, 0, 0, 0, 0, ...
。每个为0的概率是50%,在一些长时间运行的实验中,这可能会产生一个包含所有0的期望长度序列。这可能需要很长时间,但这是可能的。
回答你的问题
- 理解随机(允许重复,但使用均匀分布给你下一个值)和唯一(不允许重复,可以使用任何分布)
- 在整个过程中只使用
Random
类的一个实例或更好的RNGCryptoServiceProvider
- 生成速度在正确的实现中必须是不相关的,因为下一个值将取决于前一个状态
- 让它同步工作,然后切换到异步(但坦率地说,你不需要异步在这里)
Random
不是线程安全的