我正在研究我的多线程密码破解程序,只有数字。它必须显示已经过了多长时间才能找到密码。我使用Stopwatch
来查找它,但在函数Stopwatch
中不起作用。这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
int psw = 14995399;
Stopwatch time = new Stopwatch();
Thread Thread1 = new Thread(islem1);
Thread Thread2 = new Thread(islem2);
Thread Thread3 = new Thread(islem3);
Thread Thread4 = new Thread(islem4);
time.Start();
Thread1.Start();
Thread2.Start();
Thread3.Start();
Thread4.Start();
Thread.Sleep(1000);
time.Stop();
System.Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
static void islem1()
{
for (int i = 00000000; i < 25000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
static void islem2()
{
for (int i = 25000000; i < 50000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
static void islem3()
{
for (int i = 50000000; i < 75000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
static void islem4()
{
for (int i = 75000000; i < 100000000; i++)
{
int psw = 14995399;
if (i == psw)
{
System.Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
}
}
答案 0 :(得分:4)
这是因为你的变量
Stopwatch time = new Stopwatch();
在可见性函数之外声明。 var的可见范围是你的函数Main
。您可以将Stopwatch
作为参数传递给您的函数:
Thread1.Start(time);
或者将其声明为类字段:
class Program
{
private static Stopwatch time = new Stopwatch();
...
}
请注意,您只有一个Stopwatch
实例,如果您在一个线程中停止它,它将在所有应用程序中停止,并且在此之后将不会更改已用时间。
然后你应该从你的time.Stop();
方法中删除Main
,因为当你的线程工作longet然后1秒时,它可以导致结果。
也没理由拨打Thread.Sleep()
。只需删除这一行,您的代码就会按预期继续工作。
最后,您可以从线程函数中删除Console.ReadKey()
,因为您的主线程已经等待用户输入。
具有可配置线程数的整个解决方案可以为不同数量的线程说明有趣的结果。尝试下面的代码,它可以说明使用线程参数并减少代码行:
using System;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication4
{
internal class Program
{
private class BruteforceParams
{
public int StartNumber { get; set; }
public int EndNumber { get; set; }
}
private const int password = 14995399;
private static readonly Stopwatch time = new Stopwatch();
private static void Main(string[] args)
{
const int maxPassword = 100000000;
Console.WriteLine("Enter number of threads: ");
var threadsCountString = Console.ReadLine();
var threadsCount = int.Parse(threadsCountString);
var threads = new Thread[threadsCount];
for (int i = 0; i < threadsCount; i++)
{
var thread = new Thread(Bruteforce);
threads[i] = thread;
}
time.Start();
for (int i = 0; i < threadsCount; i++)
{
threads[i].Start(new BruteforceParams { StartNumber = i * maxPassword / threadsCount, EndNumber = (i + 1) * maxPassword / threadsCount });
}
Console.ReadKey();
}
private static void Bruteforce(object param)
{
var bp = (BruteforceParams) param;
for (int i = bp.StartNumber; i < bp.EndNumber; i++)
{
if (i == password)
{
Console.WriteLine("Şifre=" + i);
time.Stop();
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
}
}
}
}
}
答案 1 :(得分:1)
您认为time.Stop();
如何在您的函数体islem1()
或其他任何内容中工作,因为您已在Main()
函数体内定义了秒表。您一定会遇到编译错误,说当前上下文中不存在time
。
static void islem1()
{
.............
time.Stop(); // this line of code
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
}
}
相反,您可以为每个方法创建一个单独的监视并报告
static void islem1()
{
StopWatch time = Stopwatch.StartNew();
time.Stop(); // this line of code
Console.WriteLine("Time elapsed: {0}", time.Elapsed);
Console.ReadKey();
}
答案 2 :(得分:0)
使用单个Stopwatch
实例很难提取有意义的计时。
您可以选择使用针对每次测量使用新Stopwatch
的不同模式进行时序测量。
void Main()
{
var t1 = new Thread(_ => {
var sw = Stopwatch.StartNew();
DoSomething();
Console.WriteLine("took {0}ms", sw.ElapsedMilliseconds);
});
var t2 = new Thread(_ => {
var sw = Stopwatch.StartNew();
DoSomethingElse();
Console.WriteLine("took {0}ms", sw.ElapsedMilliseconds);
});
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.ReadKey();
}
void DoSomething()
{
//do something
}
void DoSomethingElse()
{
//do something
}