【问题标题】:C# Timeout with Solidworks VBA MacroSolidworks VBA 宏的 C# 超时
【发布时间】:2016-05-22 12:04:30
【问题描述】:

我在 Solidworks 插件中有一些函数调用 VBA 宏(通过 runMacro2 方法),一位同事在过去几周一直在处理这些函数。在他的代码中,他调用了一个 Solidworks 函数,该函数在某些未知条件下会挂起很长一段时间。多长时间似乎取决于零件中物体的大小和数量。考虑到我们想要从 i 自动运行它的至少一个功能,这不会做。

我尝试过使用 Thread.Join(int) 方法(如下所示),但它不起作用。我还尝试从这个答案Close a MessageBox after several seconds 修改代码,结果相同。有什么我可以在 C# 或 VBA 中做的事情来处理这个超时而不重写他的整个宏?

    public void runBB()
    {
        Stopwatch testStop = new Stopwatch();
        Thread workerThread = new Thread(bbRun);
        testStop.Start();
        workerThread.Start();
        if (!workerThread.Join(50))
        {
            workerThread.Abort();
            testStop.Stop();
            MessageBox.Show("Unable to generate Bounding Box after " + testStop.ElapsedMilliseconds/1000 + " seconds. Please enter data manually.", "Solidworks Derped Error.");
        }
        return;

    }//Still uses Macro (2-5-16)
    public static void bbRun()
    {
        iSwApp.RunMacro2(macroPath + "BOUNDING_BOX.swp", "test11", "main", 0, out runMacroError);
        return;
    }

【问题讨论】:

    标签: c# vba timeout solidworks


    【解决方案1】:

    我在打开文件时遇到了与 SOLIDWORKS 相同的问题。几乎所有关于 SO 的参考都是你永远不应该这样做,但在这种情况下,你要么必须关闭它,要么永远等待。在 C# 中,我创建了一个 callWithTimeout 方法:

        private void callWithTimeout(Action action, int timeoutMilliseconds, String errorText) {
            Thread threadToKill = null;
            Action wrappedAction = () =>
            {
                threadToKill = Thread.CurrentThread;
                action();
            };
    
            IAsyncResult result = wrappedAction.BeginInvoke(null, null);
            if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds)) {
                wrappedAction.EndInvoke(result);
            } else {
                threadToKill.Abort();
                throw new TimeoutException(errorText);
            }
        }
    

    然后将挂起的代码放在一个块中:

    bool timedOut = false;
    try {
        callWithTimeout(delegate() {
            // code that hangs here
        }, 60000, "Operation timed out.  SOLIDWORKS could not open the file.  This file will be processed later.");
    } catch (TimeoutException){
        timedOut = true;
    } finally {
        if(timedOut) {
            Process[] prs = Process.GetProcesses();
            foreach (Process p in prs) {
                if (p?.ProcessName.Equals("SLDWORKS") ?? false)
                    p?.Kill();
            }
        }
    }
    

    【讨论】:

    • 我试过这个,用“bbRun();”替换“// 挂在此处的代码”,以及我在上面显示的实际宏调用,但都不起作用。我假设你有超时,60000 是 60000 毫秒,或者 60 秒,对吗?
    • 是的 60 秒...你能通过看看会发生什么吗?它应该使用 asyncwaithandle.waitone() 调用代码块。您可能不需要该零件来终止 finally 块中的solidworks 进程。这就是我必须做的才能让它重新开始
    • 单步执行,如果 'if(result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))' 在它再次挂起之前到达了这一行。
    • 而不是iSwApp.RunMacro2(...),你可以试试Thread.Sleep(60001);,看看它在运行代码而不是宏时是否会退出。
    • Thread.Sleep(60001) 确实发挥了应有的作用。我最终将导致挂起的实际代码行放在那里 swModel.Extension.Create3DBoundingBox() 并且它仍然在相同的条件下挂起,超时没有任何区别。
    猜你喜欢
    • 1970-01-01
    • 2016-09-26
    • 2022-06-30
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多