当其他线程处于活动状态并具有try-catch时,无法在主线程中捕获异常

时间:2019-04-10 11:26:51

标签: c++ multithreading exception throw

当另一个带有try-catch的线程仍处于活动状态时,主线程无法捕获异常(该异常已在主线程中引发)。怎么解决呢? 例如:

    private void SetText(IWebElement element, string text, bool clearOldText)
    {
        // Clear old text if needed
        if (clearOldText)
        {
            LogInfo("Clearing " + element.ToString() + @" from any text.");
            SetElementValue(element, "");
        }

        element.Click();
        SetElementValue(element, text);
    }

    public string SetElementValue(IWebElement element, string value)
    {
        ScrollToElement(element);
        PaintElement(element, "yellow");
        var exec = (IJavaScriptExecutor)this;
        var script = @"
            var el = arguments[0];
            el.value = '" + value + @"';
            try 
            {
                if (""createEvent"" in document) {
                    var evt = document.createEvent(""HTMLEvents"");
                            evt.initEvent(""change"", false, true);
                            el.dispatchEvent(evt);
                        }
                else
                    el.fireEvent(""onchange"");
            }
            catch(err){ return err; }
            return ""Javascript executed."";
            ";
        LogInfo("Setting value to '" + value + "' for " + element.ToString());
        var result = exec.ExecuteScript(script, element);
        Recorder?.AddScreenshot();
        return result.ToString();
    }

3 个答案:

答案 0 :(得分:3)

不是因为捕获可连接线程会终止进程而捕获了异常,而是因为没有捕获到异常。 因此,您的程序将在执行异常处理程序之前终止。

如果在try-catch块之外声明线程,则将捕获异常。
请记住,如果引发了异常,则还需要加入线程。

答案 1 :(得分:2)

您出了点问题。我的意思是,您误解了一些东西。

这与尝试捕获无关。 “ throw”和“ try-catch”是线程内的东西,它们仅存在于当前线程上,无论在主线程或其他线程抛出时处于何种状态。

另一个线程无法捕获从当前线程引发的异常。异常不会跨越线程,除非您确实想要并实现它,例如,当前线程上的某些东西捕获了异常并将其传递给其他线程,然后在那里重新抛出/等这些异常。您没有任何此类的东西,所以不可能。

掷球后您有一个join()通话,希望throw 1会跳过。确实如此。但是,范围中还有std::thread cThread变量。

由于该线程正在运行,并且由于尚未throw 1对该线程进行join()处理,因此要查看的预期是程序终止 strong>(请参阅https://stackoverflow.com/a/13984169/717732),因为std :: thread的析构函数会检测到un-join()线程。这就是说,std::cout << "Catched exception " << e << " in main";绝对不能被调用。即使线程以某种方式完成了,您的程序仍应终止,因为它不会改变未加入()的事实(请参见https://en.cppreference.com/w/cpp/thread/thread/joinable

但是,根据库,编译器,调试器等的不同,您看到的效果可能有所不同。例如,如果在调试器中运行它,则它可能要等到所有线程完成后才能得到“等到内部线程完成”的效果。很难说。

如果您实际上看到"Catched exception " << e << "行正在运行,那么您就遇到了真正的问题。您正在运行的不是当前代码,而是您的stdlib损坏了。例如,损坏的stdlib可能在std :: thread的析构函数中执行无提示join()而不是终止程序。谁知道。损坏的lib可以做很多事情。

答案 2 :(得分:0)

感谢molbdniloquetzalcoatl。 现在,我通过使用std :: async而不是std :: thread:

使代码工作

首先,问题与线程中的try-catch无关。认为是我的错误。所以这是一个失败代码:

int main()
{
  // try-catch of main thread
  try
  {
     // run a thread
     std::thread cThread([]()
     {
     });

     // Any call to throw BEFORE thread join won't be catch.  
     // HOW TO SOLVE IT??
     throw 1;

     // wait thread finished
     cThread.join();

     // IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE 
     // CATCH.
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}

和有效的代码:

int main()
{
  std::future<void> cF;

  // try-catch of main thread
  try
  {
     // run a thread
     cF = std::async(std::launch::async, []()
     {
     });

     // You can call throw , it will be catch :)  
     throw 1;

     // wait thread finished
     if (cF.valid())
     {
        cF.get();
     }
   }
   catch (int e)
   {
      std::cout << "Catched exception " << e << " in main";
   }

   return 0;
}