我正在尝试从其他线程访问Web浏览器上的信息。在尝试访问browser.DocumentTitle
时,我收到此错误:
The name DocumentTitle does not exist in the current context
我可以成功导航到DoWork
或ProcessWebPage
方法中的网页,但我无法在不崩溃的情况下访问GetTitle
功能。我已经在这个部分工作了好几天,根本无法理解。
以下是问题代码:
浏览器代码
class BrowserInterface : Form
{
WebBrowser browser;
Thread thread;
State state;
public State State { get { return state; } }
public BrowserInterface()
{
Initialize();
}
void Initialize()
{
browser = new WebBrowser();
state = State.Null;
state = State.Initializing;
thread = new Thread(StartThread);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
while (state == State.Initializing) Thread.Sleep(20);
}
void StartThread()
{
browser = new WebBrowser();
browser.Dock = DockStyle.Fill;
browser.Name = "webBrowser";
browser.ScrollBarsEnabled = false;
browser.TabIndex = 0;
browser.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(this.Web_Completed);
Form form = new Form();
form.Controls.Add(browser);
form.Name = "Browser";
state = State.Null;
Application.Run(form);
}
public void Navigate(string url)
{
state = State.Navigating;
if (browser.IsDisposed)
Initialize();
browser.Navigate(url);
}
public string GetTitle()
{
if (InvokeRequired)
{
BeginInvoke(new MethodInvoker(() => GetTitle()));
}
return browser.DocumentTitle;
}
private void Web_Completed(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var br = sender as WebBrowser;
if (br.Url == e.Url)
state = State.Completed;
}
}
enum State
{
Initializing,
Null,
Navigating,
Completed
}
其他线程
class Controller
{
public int ThreadsAllowed;
private ManualResetEvent[] resetEvent;
private BrowserInterface[] browser;
static Thread mainThread;
bool run;
bool exit;
public Controller(int threadsAllowed)
{
ThreadsAllowed = threadsAllowed;
resetEvent = new ManualResetEvent[ThreadsAllowed];
browser = new BrowserInterface[ThreadsAllowed];
for (int i = 0; i < ThreadsAllowed; i++)
{
resetEvent[i] = new ManualResetEvent(true);
browser[i] = new BrowserInterface();
}
ThreadPool.SetMaxThreads(ThreadsAllowed, ThreadsAllowed);
mainThread = new Thread(RunThread);
mainThread.Start();
run = false;
exit = false;
}
public void Run()
{
run = true;
}
void RunThread()
{
while (true)
{
while (!run) Thread.Sleep(20);
while (mode == ScoutMode.Off) Thread.Sleep(100);
//wait for the last set to complete
WaitHandle.WaitAll(resetEvent);
if (exit)
break;
for (int i = 0; i < ThreadsAllowed; i++)
ThreadPool.QueueUserWorkItem(DoWork, i);
}
}
void DoWork(object o)
{
int i = (int)o;
if(browser[i].state == State.null)
{
…
… navigation code that works …
…
return;
}
else if(browser[i].state == State.Completed)
ProcessWebPage(i);
}
void ProcessWebPage(int i)
{
string title;
try
{
title = browser[i].GetTitle();
}
catch { return; }
}
}
答案 0 :(得分:1)
我的眼睛是你的GetTitle
功能。使用MethodInvoker
时,您正在处理void
类型的方法,也就是说,您无法从函数中获取返回值。这就是为什么你需要一个会给你回报价值的代表。
此外,您必须拥有else
语句,因此在实际需要调用时不要尝试返回该值。
class BrowserInterface : Form
{
/* ... */
private delegate string StringDelegate();
public string GetTitle()
{
/*
if (InvokeRequired)
{
BeginInvoke(new MethodInvoker(() => GetTitle()));
}
return browser.DocumentTitle;
*/
if (InvokeRequired)
{
object result = Invoke(new StringDelegate(GetTitle));
return (string)result;
}
else
return browser.DocumentTitle;
}
/* ... */
}
答案 1 :(得分:0)
首先,使用浏览器调用而不是表单。并且在调用之后你将返回代码并尝试访问browser.DocumentTitle作为后台线程的主要问题。为避免这种情况,请添加其他构造。
public string GetTitle()
{
if (this.browser.InvokeRequired)
{
this.browser.Invoke(new MethodInvoker(() => GetTitle()));
}
else
{
return browser.DocumentTitle;
}
}