【问题标题】:Program is not stepping into the Thread程序没有进入线程
【发布时间】:2017-12-15 22:10:49
【问题描述】:

线程中的功能不起作用。使用调试模式进行测试,其中程序只是跳过单步执行 Thread 表达式。在我的情况下“ThreadStart action = ()=>{...”,请看更多如下,

      DirectoryInfo directory = new DirectoryInfo(srcFile);
        FileInfo[] files = directory.GetFiles(name +  ".pdf").OrderByDescending(n => n.Name).ToArray(); 
           if (files.Length == 0) { return; }              
            foreach (FileInfo t in files)
            {
                _queue.Enqueue(t.Name);  //Insert files in to the concurrent queue.        

                    ThreadStart action = () =>
                    {
                        try
                        {
                            _semaphore.WaitOne();  // Semaphore 
                            string qfile;
                            while (_queue.TryPeek(out qfile))
                            {  
                              string srcFile = srcPath + "\\" + qfile;
                              string desFile = desPath + "\\" + qfile);

                                MoveFil(srcFile, desFile);    
                                PrintReport(desFile); 
                                _queue.TryDequeue(out qfile);
                            }                                    
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show("Moving and Printing error: " +                              
                                             e.Message);                                
                        }
                        finally
                        {
                            _semaphore.Release();
                        }
                    };
                    Thread thread = new Thread(action);
                    thread.Start();
                }

     private void PrintReport(string filePrint)
      {
        try
        {
            ProcessStartInfo info = new ProcessStartInfo();
            info.Verb = "print";
            info.FileName = filePrint;
            info.CreateNoWindow = true;
            info.WindowStyle = ProcessWindowStyle.Hidden;                

            Process p = Process.Start(info);
            p.CloseMainWindow();
            if (!p.HasExited) Thread.Sleep(5000);

        }
        catch (Exception e)
        {
            MessageBox.Show("Encounted a problem while printing! "+                                
                             e.Message);

        }
    }

【问题讨论】:

  • 因此,您正在为每个文件创建一个单独的线程,但在线程内您调用semaphore.WaitOne() 并仅在线程完成时才释放它。所以事实上,你正在序列化你的线程以一个接一个地工作。你不需要线程。如果可以同时处理两个文件,则不需要信号量,如果不能,则不需要线程...
  • 至于您的调试问题:您是否尝试在线程代码中设置断点(例如在semphore.WaitOne() 并查看此断点是否被命中?如果您只是单步执行调试器将不会) t切换到另一个线程,而且ThreadStart action = () => ... 只是一个赋值,动作的代码还没有执行,只会在Thread.Start()之后执行
  • 我注意到第三件事:您使用TryPeek() 获取队列的第一个元素。但这不会从队列中删除元素。 (见MSDN)进入信号量的第一个线程将一遍又一遍地处理队列中的第一个文件,而永远不会完成。任何其他线程都将被信号量锁定...
  • 如果你真的想让几个线程做同样的事情,你不需要在 for 循环的每次迭代中创建一个新的ThreadStart,但是你可以在进入循环之前定义它,只需创建新线程。我强烈建议您检查一下您可以并行执行哪些操作,哪些不可以。 (例如并行移动多个文件可能会起作用,打印多个报告不会)并且只需同步需要串行执行的部分
  • 我实际上需要打印并移动队列中的每个文件。你明白了我真正想做的事情。我一次需要一个进程。这意味着当一个文件完成后,它将转向另一个文件。

标签: c# .net multithreading threadpool


【解决方案1】:

当您要求调试器跳过以“ThreadAction action = () ...”开头的行时,您是在声明将在线程中执行的代码。您还没有执行它。调试器会跳过整行,因为此时代码不会执行,而是在您调用“thread.Start()”时执行。但是,调试器不知道 thread.Start 开始执行您的操作中的代码,因此它也只是越过该行。

为了单步执行线程中的代码,您必须在操作代码中设置断点。跨步是不行的。

编辑:看起来你所有的线程都在等待一个信号量。这样做没有意义。您的代码要么是异步的,在这种情况下它不需要信号量,要么是同步的,在这种情况下它不需要线程。

edit2:看来你不是由于多线程。这是一个代码示例,它使用 async/await 来执行阻塞操作而不冻结你的 UI。请注意,您必须像这样调用 NotMulthreading:

await NotMultithreading();

每个调用 NotMultithreading 的函数都必须标记为异步,一直到您的按钮处理程序。

public async Task NotMultithreading(string name, string srcPath, string desPath)
{
    //Your code sample used this line
    //DirectoryInfo directory = new DirectoryInfo(srcFile);
    //But I suspect you should use srcPath, which is probably your bug.
    DirectoryInfo directory = new DirectoryInfo(srcPath);
    FileInfo[] files = directory.GetFiles(name + ".pdf");
    foreach (FileInfo t in files)
    {
        try
        {
            var desFile = Path.Combine(desPath, t.Name);
            t.MoveTo(desFile);
            await PrintReport(desFile);
        }
        catch (Exception e)
        {
            MessageBox.Show("Moving and Printing error: " + e.Message);
        }
    }
}

private Task PrintReport(string filePrint)
{
    ProcessStartInfo info = new ProcessStartInfo();
    info.Verb = "print";
    info.FileName = filePrint;
    info.CreateNoWindow = true;
    info.WindowStyle = ProcessWindowStyle.Hidden;

    return Task.Run(() =>
    {
        try
        {
            Process p = Process.Start(info);
            p.WaitForExit();
        }
        catch (Exception e)
        {
            MessageBox.Show("Encounted a problem while printing! " +
                                e.Message);

        }
    });
}

【讨论】:

  • 在“await PrintReport(desFile)”处出现错误,是因为“任务不包含“GetAwaiter”的定义,并且没有扩展方法“GetAwaiter”接受“任务”类型的第一个参数冷被找到......并在返回 Task.Run......'Task' 不包含'Run'的定义
  • @RRah 这似乎是您的 .Net 版本的问题。您告诉我您使用的是 4.6,但 Google 告诉我当您使用低于 4.5 的 .Net 版本时会发生此错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 2011-11-27
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多