C# Timeout with Solidworks VBA Macro

本文关键字:VBA Macro Solidworks with Timeout | 更新日期: 2023-09-27 18:34:17

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

我尝试使用Thread.Join(int)方法(如下所示),但它不起作用。我还尝试修改此答案中的代码 几秒钟后关闭消息框 结果相同。我可以在 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# Timeout with Solidworks VBA Macro

我在打开

文件时遇到了 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();
        }
    }
}