C# Catching Exception From Invoked Delegate on another Thread

旧街凉风 提交于 2019-12-10 11:22:47

问题


I have some code as follows. This is running on "Thread 2"

WebBrowser browser = this.webBrowser    
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); }));
//folowed by several more similar statments

Essentially I am Invoking some methods on a WebBrowser control created on a different thread, "Thread 1".

If the element on the current page loaded in browser does not contain an element "somebtn" or "username", an exception is thrown from "Thread 1".

Is there any way to catch that exception on "Thread 2"? I know I could use try catches within the delegates and have a special delegate that returns some value(like an exception), but is there any way around that options?

Note*: I require the Thread.Sleep as the particular page requires some delay between certain events. If there was some way to combine these events into a single delegate(while retaining some form of non-blocking delay), I think that could work and I would just wrap all of them in single try catch and create a delegate that returns an exception.


回答1:


Although Control.Invoke() executes delegate over UI thread - it is still a synchronous call. Synchronous meaning Invoke will not return until the delegate has completed execution (or exception thrown). You can simply catch the exceptions thrown there.

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
}



回答2:


If you use WebBrowser.Invoke, all delegates are executes on the thread of the User Interface. So everything will be executed on one single thread. So in your question you want the UI thread to wait for itself? Assuming this is not what you want, I took some "freedom" in my answer:

There are multiple options, but I will show the most simple one:

  • Start both delegates with BeginInvoke.
  • Store the IAsyncResult of thread1 in a local variable.
  • Thread2 will do its work.
  • Thread2 will do the EndInvoke of thread1.

Code:

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);


来源:https://stackoverflow.com/questions/16517349/c-sharp-catching-exception-from-invoked-delegate-on-another-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!