C# 多线程,一个方法失败

C# 多线程,一个方法失败,c#,.net,multithreading,winapi,process,C#,.net,Multithreading,Winapi,Process,我的应用程序是系统托盘应用程序,使用C#,.NET4.0 我试图一次显示多个PDF文件,每个PDF都应该与其他窗口分开,我通过ProcessName确定,仅此而已 困难在于我需要等待用户关闭该窗口(.WaitForExit()方法),因为稍后我将删除PDF文件。问题来了 在第一个线程中,一切正常,但问题是当我尝试显示第二个PDF文件窗口processList[0]时,虽然MoveWindow函数返回true,但该窗口的句柄也正确—只有PDF窗口正在调整大小,另一个窗口失败 在main方法中,我正

我的应用程序是系统托盘应用程序,使用C#,.NET4.0

我试图一次显示多个PDF文件,每个PDF都应该与其他窗口分开,我通过ProcessName确定,仅此而已

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

在第一个线程中,一切正常,但问题是当我尝试显示第二个PDF文件窗口processList[0]时,虽然MoveWindow函数返回true,但该窗口的句柄也正确—只有PDF窗口正在调整大小,另一个窗口失败

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

然后(简化代码)

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

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

例如,Acrobat reader只启动一个进程。其他文件将作为新窗口“添加”到第一个进程中(您可以通过尝试手动打开Acrobat reader两次来检查-->将不起作用)

简而言之:如果您无法控制使用哪个PDF阅读器(并且可以确保每个文件都有一个单独的进程),那么您的方法将不起作用

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

  • 在不同的进程中查找窗口非常容易出错(除非该进程是以这种方式明确设计的…)
  • 解决方案同样取决于阅读器应用程序(您无法确定Acrobat和Nitro是否使用类似的体系结构来命名两个阅读器)
  • 原则上,如果这个特性非常重要,你应该考虑买一个PDF查看器组件,它可以显示PDF作为你自己进程的窗口。 编辑 第二个线程没有等待的原因是向第一个进程“添加”文件的功能使用了一个临时进程:

  • 新文件的临时进程已启动
  • 临时进程检查应用程序是否已在运行
  • 临时进程通知第一个进程打开特定文件
  • 临时进程关闭

  • 因此,等待该进程几乎会立即返回,因为该进程已经停止(或将在几毫秒内停止)。

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

    例如,Acrobat reader只启动一个进程。其他文件将作为新窗口“添加”到第一个进程中(您可以通过尝试手动打开Acrobat reader两次来检查-->将不起作用)

    简而言之:如果您无法控制使用哪个PDF阅读器(并且可以确保每个文件都有一个单独的进程),那么您的方法将不起作用

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

  • 在不同的进程中查找窗口非常容易出错(除非该进程是以这种方式明确设计的…)
  • 解决方案同样取决于阅读器应用程序(您无法确定Acrobat和Nitro是否使用类似的体系结构来命名两个阅读器)
  • 原则上,如果这个特性非常重要,你应该考虑买一个PDF查看器组件,它可以显示PDF作为你自己进程的窗口。 编辑 第二个线程没有等待的原因是向第一个进程“添加”文件的功能使用了一个临时进程:

  • 新文件的临时进程已启动
  • 临时进程检查应用程序是否已在运行
  • 临时进程通知第一个进程打开特定文件
  • 临时进程关闭

  • 因此,等待该进程几乎会立即返回,因为该进程已经停止(或将在几毫秒内停止)。

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

    例如,Acrobat reader只启动一个进程。其他文件将作为新窗口“添加”到第一个进程中(您可以通过尝试手动打开Acrobat reader两次来检查-->将不起作用)

    简而言之:如果您无法控制使用哪个PDF阅读器(并且可以确保每个文件都有一个单独的进程),那么您的方法将不起作用

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

  • 在不同的进程中查找窗口非常容易出错(除非该进程是以这种方式明确设计的…)
  • 解决方案同样取决于阅读器应用程序(您无法确定Acrobat和Nitro是否使用类似的体系结构来命名两个阅读器)
  • 原则上,如果这个特性非常重要,你应该考虑买一个PDF查看器组件,它可以显示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");
                    }
                }
    
    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);
    }