异步随机字母生成太快

本文关键字:随机 异步 | 更新日期: 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不是线程安全的