I’m trying to generate 900,000 keys and store them to a db.
Each value has to be 8 chars and different from generated ones.
Here is my code look like, it’s doing ok but it’s too slow…
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.Visible = false;
Generate();
}
public int num = 0;
private void Den1()
{
for (int i = 0; i < 900000; i++)
{
string randomStr = RandomString(8);
string textToSearchFor = randomStr;
int index = richTextBox1.Text.IndexOf(textToSearchFor, StringComparison.OrdinalIgnoreCase);
if (index >= 0)
{
MessageBox.Show("Duplicate ignored from 1!");
i--;
}
else
{
richTextBox1.Text += randomStr + "\n";
num++;
}
label1.Text = "" + num;
}
richTextBox1.Visible = true;
}
public void Generate()
{
CheckForIllegalCrossThreadCalls = false;
Thread thread1 = new Thread(Deneme1);
thread1.Start();
}
private string RandomString(int length, string allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "length cannot be less than zero.");
if (string.IsNullOrEmpty(allowedChars)) throw new ArgumentException("allowedChars may not be empty.");
const int byteSize = 0x100;
var allowedCharSet = new HashSet<char>(allowedChars).ToArray();
if (byteSize < allowedCharSet.Length) throw new ArgumentException(String.Format("allowedChars may contain no more than {0} characters.", byteSize));
// Guid.NewGuid and System.Random are not particularly random. By using a
// cryptographically-secure random number generator, the caller is always
// protected, regardless of use.
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider())
{
var result = new StringBuilder();
var buf = new byte[128];
while (result.Length < length)
{
rng.GetBytes(buf);
for (var i = 0; i < buf.Length && result.Length < length; ++i)
{
// Divide the byte into allowedCharSet-sized groups. If the
// random value falls into the last group and the last group is
// too small to choose from the entire allowedCharSet, ignore
// the value in order to avoid biasing the result.
var outOfRangeStart = byteSize - (byteSize % allowedCharSet.Length);
if (outOfRangeStart <= buf[i]) continue;
result.Append(allowedCharSet[buf[i] % allowedCharSet.Length]);
}
}
return result.ToString();
}
}
}
Well to start with, I would generate them all and then put them into the UI. I also wouldn’t use
string.IndexOfto find if you’ve already got a match. Use aHashSet<string>:You also shouldn’t be setting
CheckForIllegalCrossThreadCallsto false. Just generate them all in the background and then useInvoketo get to the UI thread to update your UI. If you really want to update as you go, you could do so periodically… although I wouldn’t put them all into a single text box.Next, I’d look at the
RandomStringmethod. Do you really need to create a newRNGCryptoServiceProvideron every iteration? Why not create one and then reuse it?Likewise, why bother creating a new
HashSet<char>and callingToArrayon every call? It sounds like you should probably have a separate class as aRandomCodeGeneratorwhich remembers:That will let you get away from doing a lot of setup work on every iteration.
I’d then personally create a
char[]of the right size and just iterate until you’ve filled it, then create a string from that… I don’t see the need forStringBuilder… but that’s probably not hurting you.