许多线程,一种方法失败

时间:2014-06-26 12:20:17

标签: c# .net multithreading winapi process

我的应用程序是使用C#,.NET 4.0的系统托盘应用程序。

我正在尝试一次显示多个PDF文件,每个PDF应该与其他窗口分开屏幕,我通过ProcessName确定,这就是全部。

困难在于我需要等到用户关闭该窗口(.WaitForExit()方法),因为稍后我将删除PDF文件。而这里的问题来了。

在第一个帖子中一切都很顺利但问题是当我尝试显示第二个PDF文件窗口processList [0] THOUGH MoveWindow函数返回true,并且该窗口的句柄也正确只有pdf窗口正在调整大小,其他窗口失败。

在main方法中我唯一正在创建的线程(我每次都会调用这段代码,每次用户都希望看到pdf文件):

Thread pdfThread = new Thread(() => ShowPdfFile(fullPath));
pdfThread.Start();

然后(简化代码)

public static void ShowPdfFile(string fileName)
        {
            try
            {
                 Process pdfProcess = Process.Start(fileName);
                 Thread.Sleep(500);
                 string windowTitle = GetActiveWindowTitle();
                 IntPtr pdfHandle = (IntPtr)FindWindow(null, windowTitle);
                 MoveWindow(pdfHandle, 0, 0, 0, 0, true);

                 Process[] processList = Process.GetProcessesByName("someProcess");
                 MoveWindow(processList[0].MainWindowHandle, 0, 0, 0, 0, true);

                 pdfProcess.WaitForExit();
                 MoveWindow(processList[0].MainWindowHandle, 0, 0, max, max, true);
            }
            catch (Exception ex)
            {
                LogToFile(ex);
            }
            finally
            {
                try
                {
                    File.Delete(fileName);
                }
                catch
                {
                    LogToFile("Cannot delete file");
                }
            }

更新:好吧,我整天都在调试它,但是现在我注意到在第二个线程上它没有在线等待pdfProcess.WaitForExit(); 我应该更改什么来强制线程等待确切的pdfProcess退出?

3 个答案:

答案 0 :(得分:2)

您的使用存在一个基本问题: 您为每个文件启动外部PDF应用程序。但是,这并不能确保您拥有多个流程。

例如,Acrobat reader只启动一个进程。其他文件将被“添加”为第一个进程的新窗口(您可以通过尝试手动打开Acrobat reader两次来检查这一点 - >将无效)。

简而言之:如果您无法控制使用哪个PDF阅读器(并且可以确保您对EACH文件只有一个进程),那么您的方法将无效。

注意:从理论上讲,可以等到用户关闭包含特定文件的“阅读器窗口”。不过我强烈建议不要这样做:

  1. 在不同的流程中查找窗口非常容易出错(除非流程是以这种方式明确设计的......)
  2. 解决方案将再次依赖于读者应用程序(您不能确定Acrobat和Nitro使用类似的架构来命名两个读者)
  3. 主要是,如果此功能非常重要,您应该考虑购买一个PDF查看器组件,该组件允许将PDF显示为您自己进程的窗口。

    修改 第二个线程没有等待的原因是“向第一个进程”添加“文件”的功能使用临时进程:

    1. 为新文件启动临时流程
    2. 临时进程检查应用程序是否已在运行
    3. 临时进程通知第一个进程打开特定文件
    4. 临时进程关闭。
    5. 因此,等待该过程几乎立即返回,因为有问题的过程已经停止(或者将在几毫秒内停止)。

答案 1 :(得分:1)

Daniel是对的,不过我找到了解决方案!在这里,也许有人会使用它 小评:我们必须使用winapi解决方案而不是.WaitForExit() 最重要的部分是while循环,等待关闭pdf窗口 请记住,FindWindow()和IsWindow()方法来自user32.dll(winapi) 这个代码运行过程基于它的路径,然后让它处理并等待它的关闭。

Process pdfProcess = new Process();
pdfProcess.StartInfo.FileName = filePath;
if (pdfProcess.Start())
{
    Thread.Sleep(500);
    Process[] processlist = Process.GetProcesses();
    string windowTitle = string.Empty;

    foreach (Process process in processlist)
    {
        if (!String.IsNullOrEmpty(process.MainWindowTitle) && process.MainWindowTitle.Contains(fileName))
        {
            windowTitle = process.MainWindowTitle;
        }
    }
    IntPtr pdfHandle = FindWindow(null, windowTitle);

    while (IsWindow(pdfHandle) && userExitedApp == false)
        Thread.Sleep(100);
}

答案 2 :(得分:0)

多个线程可以一个接一个地使用一个方法。也许这个视频会有所帮助 https://www.youtube.com/watch?v=XhGXh9Z5GTw&feature=em-upload_owner