【问题标题】:Stopwatch and ReadKey don't work properly秒表和 ReadKey 无法正常工作
【发布时间】:2016-01-01 20:33:57
【问题描述】:

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

【问题讨论】:

  • 在每个线程函数中创建一个单独的Stopwatch。不要创建一个并在线程之间共享它。
  • 这不是“不起作用”,而是“无法编译”。这是一个巨大的差异。

标签: c# multithreading stopwatch console.readkey


【解决方案1】:

这是因为你的变量

Stopwatch time = new Stopwatch();

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

Thread1.Start(time);

或者将其声明为类字段:

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

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

然后你应该从你的Main 方法中删除time.Stop();,因为当你的线程工作时间超过 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);
                }
            }
        }
    }
}

【讨论】:

  • 我不确定我是否理解您的情况,但我认为您无需在每个线程函数中获取 ReadKey。尝试删除它,它会继续按预期工作。另外,删除 time.Stop(); Main 函数中的行。
  • 这对 OP 来说并不是那么有用,因为他们在单个 Stopwatch 实例上多次调用 Stop。这会产生意想不到的结果。
  • 这是一个让我了解暴力破解密码和多线程密码破解时间差的作业。
  • 好的。然后,您也无需在每个线程函数中声明int psw = 14995399;,您可以在我的回答中将其声明为类字段,如StopWatch。通过线程计数系统创建可配置也很有趣。您可以从控制台读取 N,创建 N 个踏板并传递给每个线程开始搜索编号 i * 100000000 / N,其中 i 是您的线程索引。这不是你的作业,但它可能很有趣,而且不会花很长时间;)
  • 这是个好主意,但现在我要为并行任务做密码破解,我不知道如何使用它,这是什么想法,这是最后一个晚上做作业:)
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2017-12-20
      • 2017-08-26
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      • 2014-05-09
      • 2021-08-10
      相关资源
      最近更新 更多