【发布时间】: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