秒表和 ReadKey 无法正常工作

Stopwatch and ReadKey don't work properly

我正在研究我的多线程密码破解程序,只有数字。它必须显示找到密码已经过了多长时间。我用 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();
            }
        }
    }
  }
}

您认为 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();
 }

因为你的变量

Stopwatch time = new Stopwatch();

在可见性函数之外声明。 var 的可见范围是你的函数Main。您可以将 Stopwatch 作为参数传递给您的函数:

Thread1.Start(time);

或将其声明为 class 字段:

class Program
{
    private static Stopwatch time = new Stopwatch();
    ...
}

请注意,您只有一个 Stopwatch 实例,如果您在一个线程中停止它,它将在所有应用程序中停止,并且经过的时间在那之后不会改变。

那么你应该从你的 Main 方法中删除 time.Stop(); 因为当你的线程工作超过 1 秒时它会导致结果出现问题。

也没有理由打电话给Thread.Sleep()。只需删除此行,您的代码就会继续按预期工作。

最后,您可以从线程函数中删除 Console.ReadKey(),因为您的 main-thread 已经在等待用户输入。

具有可配置线程数的整个解决方案可以说明不同线程数的有趣结果。试试下面的代码,它可以说明如何使用线程参数并减少代码行数:

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);
                }
            }
        }
    }
}

使用单个 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
}