【问题标题】:WPF c# - Execute a task continuously and allow execution of another taskWPF c# - 连续执行一个任务并允许执行另一个任务
【发布时间】:2016-05-12 07:08:36
【问题描述】:

我正在使用程序通过 c# 运行宏:

任务 1:

 EXCELApplicationObj.GetType().InvokeMember("Run",
       System.Reflection.BindingFlags.Default |
       System.Reflection.BindingFlags.InvokeMethod,
       null, EXCELApplicationObj, oRunArgs);

但是当这个函数运行时,我想通过它的标题名来检查一个窗口的出现,为此我使用了这个:

任务 2:

Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        process.ProcessName, process.Id, process.MainWindowTitle);
        if (process.MainWindowTitle == "Untitled - Notepad") {
            process.Kill();
        }
    }
}

但问题是我想在进程中运行这个并行,以便我想执行宏并且当新窗口出现名为“无标题 - 记事本”时,我想关闭它。 任何stackoverflowers都可以给我任何指导。 听说过线程,但我不太了解线程..

更新: 我在找什么:

连续执行 Task2 并允许执行 Task1。

【问题讨论】:

    标签: c# multithreading concurrency


    【解决方案1】:

    这是一个在运行一些代码时自动关闭窗口的示例:

    static void Main() {
    
        // execute AsyncCloseTopWindow in parallel to close a window named "Untitled - Notepad"
        var thread = new Thread(AsyncCloseTopWindow);
        thread.IsBackground = true;          
        thread.Start("Untitled - Notepad");
    
        // execute the macro while AsyncCloseTopWindow is running 
        //...
    
        // exit AsyncCloseTopWindow
        thread.Interrupt();
    }
    
    private static void AsyncCloseTopWindow(object windowTitle) {
        try {
            while (true) {
    
                // close any window matching the title
                IntPtr hwnd = FindWindow(IntPtr.Zero, (string)windowTitle);
                if (!hwnd.Equals(IntPtr.Zero)) {
                    SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                }
    
                // wait 30ms
                Thread.Sleep(30);
            }
        } catch (ThreadInterruptedException) { }
    }
    
    private const UInt32 WM_CLOSE = 0x0010;
    
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern IntPtr FindWindow(IntPtr lpClassName, string lpWindowName);
    
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
    

    【讨论】:

    • 嗨@Florent B.,知道如何在wpf中使用DllImport,它显示错误。
    • 错误 4 找不到类型或命名空间名称“DllImport”(您是否缺少 using 指令或程序集引用?
    • 我认为它将在 c# winfroms 中使用,但不会在 wpf 中使用
    • 我刚刚测试了一个新的 WPF 应用程序。它按预期工作。完整签名是System.Runtime.InteropServices.DllImport。注意DllImport需要放在一个类中
    • 非常感谢...我一直在处理这个问题...非常感谢...
    【解决方案2】:

    我认为您希望循环运行“杀死所有未命名的记事本进程”。考虑到这一点,试试这个......

    public void killNotepad()
        {
            Process[] processlist = Process.GetProcesses();
            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    //process.ProcessName, process.Id, process.MainWindowTitle);
                    if (process.MainWindowTitle == "Untitled - Notepad")
                    {
                        process.Kill();
                    }
                }
            }
        }
    
        public void killNotepadRunAsync()
        {
            System.Threading.Thread th = new System.Threading.Thread(() =>
            {
                while (true)
                {
                    killNotepad();
                    System.Threading.Thread.Sleep(300);
                }
            });
            th.SetApartmentState(System.Threading.ApartmentState.STA);
            th.Start();
        }
    

    “killNotepad()”方法在一个由“killNotepadRunAsync()”方法执行的线程中多次运行,所以在需要的地方调用killNotepadRunAsync()方法。

    System.Threading.Thread.Sleep(300) 使线程休眠 300 毫秒,然后再进行下一次 Process.getProcesses() 调用,这让您的 CPU 有时间喘口气。

    嗯,我注释掉了第八行,因为我不确定你想用它做什么。这也是一个语法错误。

    玩得开心!

    【讨论】:

    • 我的宏调用出现异常,上面写着:An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll Additional information: Exception has been thrown by the target of an invocation.
    【解决方案3】:

    您可以使用单独的线程来运行查找窗口并关闭它们的代码。您需要在对象中使用私有字段stopClosingWindows 来告诉并行线程何时终止。

    private bool stopClosingWindows;

    您需要一个单独的方法来执行查找窗口并循环关闭它们的操作:

    private void ParallelCloseWindows()
    {
        while (!stopClosingWindows)
        {
            // Only look every 200ms so we don't waste processor ressources
            Thread.Sleep(200);
    
            // perform the task
            Process[] processlist = Process.GetProcesses();
            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    if (process.MainWindowTitle == "Untitled - Notepad")
                    {
                        process.Kill();
                    }
                }
            }
        }
    }
    

    现在,在您开始执行宏的实际代码之前,请将 stopClosingWindows 设置为 false 并启动并行线程。在您的实际代码执行宏之后,将 stopClosingWindows 设置为 false 以指示它可以停止和终止的线程。

    使用 try/finally 以便并行线程停止,即使在执行宏时出现异常。

    stopClosingWindows = false;
    try
    {
        // Create a new thread that should execute the method ParallelCloseWindows in parallel
        var thread = new Thread(ParallelCloseWindows);
    
        // set isBackground to true so that this thread would not prevent your application from closing when 
        // we forget to terminate it
        thread.IsBackground = true;
    
        // and start the new thread
        thread.Start();
    
        EXCELApplicationObj.GetType().InvokeMember("Run", 
                System.Reflection.BindingFlags.Default 
                | System.Reflection.BindingFlags.InvokeMethod,
                null, EXCELApplicationObj, oRunArgs);
    }
    finally
    {
        stopClosingWindows = true;
    }
    

    【讨论】:

    • 谢谢@NineBerry ...但是当我尝试时,我在宏调用行遇到异常...任何想法!
    • An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll Additional information: Exception has been thrown by the target of an invocation.
    • 我会说当宏尝试对它创建的记事本窗口执行某些操作时,宏中会发生错误。似乎您不能简单地关闭记事本实例。也许在宏完成执行后将它们全部关闭?
    • 感谢 NineBerry,但宏只有在您关闭记事本时才会退出......否则我必须手动关闭它......
    猜你喜欢
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 2013-02-13
    • 2012-06-28
    • 2011-07-03
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多