C#从另一个线程上调用的委托捕获异常

C#从另一个线程上调用的委托捕获异常,c#,multithreading,delegates,invoke,C#,Multithreading,Delegates,Invoke,我有一些代码如下。这是在“线程2”上运行的 本质上,我是在调用在不同线程“线程1”上创建的WebBrowser控件上的一些方法 如果浏览器中加载的当前页面上的元素不包含元素“somebtn”或“username”,则会从“线程1”引发异常 有没有办法在“线程2”上捕获该异常?我知道我可以在委托中使用try-catch,并有一个特殊的委托返回一些值(比如异常),但是有没有办法绕过这个选项呢 注意*:我需要线程。睡眠,因为特定页面在某些事件之间需要一些延迟。如果有某种方法可以将这些事件组合成一个委托

我有一些代码如下。这是在“线程2”上运行的

本质上,我是在调用在不同线程“线程1”上创建的WebBrowser控件上的一些方法

如果浏览器中加载的当前页面上的元素不包含元素“somebtn”或“username”,则会从“线程1”引发异常

有没有办法在“线程2”上捕获该异常?我知道我可以在委托中使用try-catch,并有一个特殊的委托返回一些值(比如异常),但是有没有办法绕过这个选项呢


注意*:我需要线程。睡眠,因为特定页面在某些事件之间需要一些延迟。如果有某种方法可以将这些事件组合成一个委托(同时保留某种形式的非阻塞延迟),我认为这可能会起作用,我只需将所有事件包装在一个try-catch中,并创建一个返回异常的委托。

如果使用WebBrowser.Invoke,所有委托都会在用户界面的线程上执行。因此,所有操作都将在一个线程上执行。那么,在您的问题中,您希望UI线程等待自己?假设这不是你想要的,我在回答中选择了一些“自由”:

有多个选项,但我将展示最简单的一个:

  • 用BeginInvoke启动两个代理
  • 将thread1的
    IAsyncResult
    存储在局部变量中
  • Thread2将完成它的工作
  • Thread2将执行thread1的
    EndInvoke
代码:


尽管
Control.Invoke()
通过UI线程执行委托,但它仍然是一个同步调用。同步含义
Invoke
在委托完成执行(或引发异常)之前不会返回。您可以简单地捕获抛出的异常

WebBrowser browser = this.webBrowser;
try {    
    browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("somebutton").InvokeMember("click"); }));
    Thread.Sleep(500);
    browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("username").SetAttribute("value", username); }));
} catch(Exception e) 
{
    //catch in Thread 2
}

如果我在MSDN中查看
WebBrowser
class(),我看不到任何
Invoke
方法。您使用的是哪一个?Invoke是所有UI控件的方法…它允许从其他线程等更新控件。如果您的假设为真,并且您调用Control.Invoke,则在UI线程上调用所有委托。所以在同一条线上。这就是你想要的吗?
WebBrowser browser = this.webBrowser;
MethodInvoker thread1 = delegate
{
    browser.Document.GetElementById("somebutton").InvokeMember("click");
};
IAsyncResult result1 = thread1.BeginInvoke(null, null);
Thread.Sleep(500);
MethodInvoker thread2 = delegate
{
    browser.Document.GetElementById("username").SetAttribute("value", username);
    try
    {
        thread1.EndInvoke(result1);
    }
    catch (Exception ex)
    {
        // Exception of thread1.
    }
};
thread2.BeginInvoke(null, null);
WebBrowser browser = this.webBrowser;
try {    
    browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("somebutton").InvokeMember("click"); }));
    Thread.Sleep(500);
    browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("username").SetAttribute("value", username); }));
} catch(Exception e) 
{
    //catch in Thread 2
}