【问题标题】:The code works but it lags when it works. It works with foreach and loop it该代码有效,但在有效时会滞后。它适用于 foreach 并循环它
【发布时间】:2014-09-12 15:15:10
【问题描述】:

当代码运行如此滞后时,它会非常好,这样它在运行时就不会出现滞后。

代码的工作原理:

它会在计算机中搜索文件,然后在找到它时更改文件,但如果文件正在运行,则行将循环,直到它设法完成其工作。

主类

public Form1(string[] Args)
    {
        InitializeComponent();
        backgroundWorker1.RunWorkerAsync();
    }    

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Thread.Sleep(1000); // One second.Thread.Sleep(1000); // One second.
        MessageBox.Show("Testing");
        Fille mc = new Fille();
        mc.Search();
    }

填充类

private static ArrayList list2 = new ArrayList();
private static ArrayList listRemove = new ArrayList();


public void Search()
    {
        try
        {
            foreach (string file in Directory.EnumerateFiles(@"C:\Users\user\Downloads\MCFILE\trrtrt\", "*.exe", SearchOption.AllDirectories))
            {
                // Display file path.
                if (SHA1Hash.GetSHA1Hash(file) == "1233456") // fake SHA1Hash
                {
                    try
                    {
                        COPYWithReplace(@"C:\Users\user\Downloads\MCFILE\Fake2\Test.exe", file);
                    }
                    catch (IOException)
                    {
                        // log errors
                        if (list2.Count == 0)
                        {
                            list2.Add(file);
                            Thread thread = new Thread(new ThreadStart(Test2));
                            thread.Start();
                        }
                        else
                        {
                            Thread thread = new Thread(new ThreadStart(Test2));
                            thread.Abort();
                            list2.Add(file);
                            thread.Join();
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // log errors
        }
    }

private void Test2()
    {
        if (list2.Count == 0)
        {
        }
        else
        {

            foreach (string _item in list2)
            {
                try
                {
                    //Run
                    COPYWithReplace(@"C:\Users\user\Downloads\MCFILE\Fake2\Test.exe", _item);
                    listRemove.Add(_item);
                }
                catch (IOException)
                {
                    //error
                }
            }
            foreach (var Remove in listRemove)
            {
                list2.Remove(Remove);
            }
            listRemove.Clear();
            if (list2.Count == 0)
            {
            }
            else
            {
                Thread thread = new Thread(new ThreadStart(Test2));
                thread.Start();
            }

        }
    }

因为我发现了问题,所以我创建了一个新线程。但现在只是滞后了。

【问题讨论】:

  • 你说的滞后是什么意思?您是否尝试过任何方法来找出问题所在?
  • 滞后循环。 foreach
  • 当再次循环这段代码然后滞后它。 Test2() ---> foreach
  • 我想也许我可以通过阅读代码来了解您要做什么,因为您的问题难以理解。但在这种情况下,您的代码比您的文本描述更加复杂。你能用语言告诉我们你想要完成什么,并解释你所说的“它滞后”是什么意思吗?
  • i.imgur.com/HRgO0Kp.png 图片更详细地说明了它的工作原理。如果没有成功,它将更改文件,所以如果成功,请尝试。

标签: c# arraylist foreach


【解决方案1】:

我怀疑它“滞后”的原因是因为您的系统处于一个非常复杂但处理器密集型和 I/O 密集型循环中。如果文件第一次测试失败,您的代码会启动一个线程再次尝试它。如果失败了,那么你启动另一个线程再试一次,起泡,冲洗,重复。

这绝对会杀死性能。你基本上是这样做的:

while (forever)
{
    if I can overwrite the file
    {
        break;
    }
}

除非您尝试写入多个文件,否则您将针对每个文件执行该循环。同时。而且您不只是使用循环。取而代之的是,您启动和停止线程就像没人管事一样。

是的,这会让你的电脑变慢。

更合理的方法是使用一个线程进行第一次检查,并使用一个计时器来限制您进行其他检查的频率。通信是通过一个简单的队列进行的,因为一次只有一个线程会访问它。

以下是我的建议:

private static Queue<string> filesToCheck = new Queue<string>();
private System.Timers.Timer copyTimer;

public void Search()
{
    try
    {
        foreach (string file in Directory.EnumerateFiles(@"C:\Users\user\Downloads\MCFILE\trrtrt\", "*.exe", SearchOption.AllDirectories))
        {
            // Display file path.
            if (SHA1Hash.GetSHA1Hash(file) == "1233456") // fake SHA1Hash
            {
                if (!TryToCopy(file))  // See function below
                {
                    filesToCheck.Enqueue(file);
                }
            }
        }
        // Checked all the files once.
        // If there are any in the queue, start the timer.
        if (filesToCheck.Count > 0)
        {
            copyTimer = new System.Timers.Timer(CopyTimerProc, null, 1000, Timeout.Infinite);
        }

    }
    catch (Exception)
    {
        // do your error handling
    }
}

private void CopyTimerProc(object state)
{
    string filename = filesToCheck.Dequeue();
    if (TryToCopy(filename))
    {
        // success. If the queue is empty, kill the timer.
        if (filesToCheck.Count == 0)
        {
            copyTimer.Dispose();
        }
    }
    else
    {
        // File still locked.
        // Put it back on the queue and reset the timer.
        filesToCheck.Enqueue(filename);
        copyTimer.Change(1000, 0);
    }
}

private bool TryToCopy(string filename)
{
    try
    {
        COPYWithReplace(@"C:\Users\user\Downloads\MCFILE\Fake2\Test.exe", filename);
        return true;
    }
    catch (IOException)
    {
        // log error
        return false;
    }
}

计时器是一次性的,每次计时后都会重置。我这样做的原因是为了防止在前一个滴答仍在处理时出现另一个滴答。毕竟,复制文件需要时间。

没有理由用一堆线程来做这件事。无论如何,文件系统一次只能做一件事,而且在您等待文件可用时多花一两秒钟不会对任何事情造成伤害。

【讨论】:

  • 它可以处理多少个文件?还是一次只能处理一个文件?
  • @BigLoser:任何数量的文件都可以进入队列,代码每秒会检查一个文件。它一次只复制一个文件,但由于它们都在同一个磁盘驱动器上,所以复制所有文件的总时间将大致相同——可能更少——因为磁盘驱动器不能做更多一次不止一件事。代码非常简单。花几分钟的时间研究一下,你就会明白它是如何工作的。
  • 我应该从 backgroundWorker1 启动它然后转身运行这个吗?搜索()
  • @BigLoser:这取决于你。您当然可以从后台工作人员运行它。它将执行第一步(建立队列),后台工作人员将退出。如果队列中有项目,则计时器将继续每秒滴答一次,直到队列为空。
猜你喜欢
  • 2020-06-14
  • 2012-10-19
  • 2017-09-01
  • 2019-12-16
  • 2021-08-15
  • 2021-11-06
  • 1970-01-01
  • 2017-06-24
  • 2016-09-02
相关资源
最近更新 更多