gpt4 book ai didi

c# - 如何用另一个 DocumentText 更新 DocumentText

转载 作者:太空宇宙 更新时间:2023-11-03 13:24:39 34 4
gpt4 key购买 nike

我有一个 Windows 窗体,它有一个 WebBrowser 控件名称 formWebBrowser。我正在使用另一个名为 newThreadBrowser 的 WebBrowser 实例创建一个新的非 UI 线程。引用 WebBrowser Control in a new thread

当触发 documentcompleted 事件时,我可以使用 C# - Updating GUI using non-main Thread 中提到的方法将 url 写入文本框

现在,我正在尝试从“newThreadBrowser”的 html 更新“formWebBrowser”的 html。它导致异常说 Specified cast is not valid。

WebBrowser control: "Specified cast is not valid." ,接受的答案说 -

WebBrowser is a COM component under the hood. An apartment threaded one, COM takes care of calling its methods in a thread-safe way. Your Navigate() call works for that reason, it is actually executed on the UI thread. What doesn't work is the DocumentText property, it is implemented in the .NET wrapper and they somewhat fumbled the code. It bombs when the COM interop support in the CLR notices that a thread in the MTA tries to access a property of a component that lives on an STA.

问题

为了在 formWebBrowser 中呈现来自 newThreadBrowser 的 html,我应该怎么做?我不确定 Control.Invoke() 如何解决这个问题。

注意:此应用程序的性能不是关键的。所以即使需要一些时间来执行也没关系。

引用

  1. How to change webBrowser DocumentText?
  2. How do I extract info from a webpage?
  3. http://htmlagilitypack.codeplex.com/

来自 WebBrowser.DocumentText Property

Use this property when you want to manipulate the contents of an HTML page displayed in the WebBrowser control using string processing tools. You can use this property, for example, to load pages from a database or to analyze pages using regular expressions. When you set this property, the WebBrowser control automatically navigates to the about:blank URL before loading the specified text. This means that the Navigating, Navigated, and DocumentCompleted events occur when you set this property, and the value of the Url property is no longer meaningful.

代码

public partial class Form1 : Form
{

public void WriteToTextBoxEvent(object sender, WebBrowserDocumentCompletedEventArgs e)
{

#region Textbox
if (this.textBox1.InvokeRequired)
{
//BeginInvoke is Asynchronus
this.textBox1.BeginInvoke(new Action(() => WriteToTextBoxEvent(sender, e)));
}
else
{
textBox1.Text = e.Url.ToString();
}
#endregion

#region WebBrowser
if (this.formWebBrowser.InvokeRequired)
{
//BeginInvoke is Asynchronus
this.textBox1.BeginInvoke(new Action(() => WriteToTextBoxEvent(sender, e)));
}
else
{
var newThreadBrowser = sender as WebBrowser;
if (sender != null)
{
//The function evaluation requires all threads to run
formWebBrowser.DocumentText = newThreadBrowser.DocumentText;
}
}
#endregion
}



System.Windows.Forms.TextBox textBox1 = new TextBox();
System.Windows.Forms.WebBrowser formWebBrowser = new WebBrowser();

public Form1()
{

WriteLogFunction("App Satrt");

// Web Browser
#region Web Browser
formWebBrowser.Location = new Point(10, 20);
formWebBrowser.Size = new Size(1200, 900);
this.Controls.Add(formWebBrowser);

textBox1.Location = new Point(0, 0);
textBox1.Size = new Size(800, 10);
this.Controls.Add(textBox1);

var th = new Thread(() =>
{
var newThreadBrowser = new WebBrowser();

//To Process the DOM.
newThreadBrowser.DocumentCompleted += browser_DocumentCompleted;

//To update URL textbox
newThreadBrowser.DocumentCompleted += WriteToTextBoxEvent;

newThreadBrowser.ScriptErrorsSuppressed = true;
newThreadBrowser.Navigate(GetHomoePageUrl());

Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();

#endregion

// Form1
this.Text = "B2B Crawler";
this.Size = new Size(950, 950);

}

List<string> visitedUrls = new List<string>();
List<string> visitedProducts = new List<string>();

private void ExerciseApp(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var wbReceived = sender as WebBrowser;
int catalogElementIterationCounter = 0;
var elementsToConsider = wbReceived.Document.All;
string productUrl = String.Empty;
bool isClicked = false;

foreach (HtmlElement e1 in elementsToConsider)
{
catalogElementIterationCounter++;
string x = e1.TagName;
String idStr = e1.GetAttribute("id");
if (!String.IsNullOrWhiteSpace(idStr))
{
//Each Product Navigation
if (idStr.Contains("catalogEntry_img"))
{
productUrl = e1.GetAttribute("href");
if (!visitedProducts.Contains(productUrl))
{
WriteLogFunction("productUrl -- " + productUrl);
visitedProducts.Add(productUrl);
isClicked = true;

e1.InvokeMember("Click");
//nextNavigationUrl = productUrl;

break;
}

}
}
}


if (visitedProducts.Count == 4)
{
visitedProducts = new List<string>();
isClicked = true;
HomoePageNavigate(wbReceived);
}

if (!isClicked)
{
HomoePageNavigate(wbReceived);
}
}

void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
ExerciseApp(sender, e);
}


private string GetHomoePageUrl()
{
return @"C:\Samples_L\MyTableTest.html";
}

private void HomoePageNavigate(WebBrowser bw)
{
WriteLogFunction("HomoePageNavigate");
bw.Navigate(GetHomoePageUrl());
}

private void WriteLogFunction(string strMessage)
{
using (StreamWriter w = File.AppendText("log.txt"))
{
w.WriteLine("\r\n{0} ..... {1} ", DateTime.Now.ToLongTimeString(), strMessage);
}
}

}

MyTableTest.html

<html>
<head>

<style type="text/css">
table {
border: 2px solid blue;
}

td {
border: 1px solid teal;
}
</style>

</head>
<body>

<table id="four-grid">
<tr>
<td>
<a href="https://www.wikipedia.org/" id="catalogEntry_img63666">

<img src="ssss"
alt="B" width="70" />
</a>
</td>
<td>
<a href="http://www.keralatourism.org/" id="catalogEntry_img63667">

<img src="ssss"
alt="A" width="70" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://stackoverflow.com/users/696627/lijo" id="catalogEntry_img63664">

<img src="ssss"
alt="G" width="70" />
</a>
</td>
<td>
<a href="http://msdn.microsoft.com/en-US/#fbid=zgGLygxrE84" id="catalogEntry_img63665">

<img src="ssss"
alt="Y" width="70" />
</a>
</td>
</tr>

</table>
</body>

</html>

最佳答案

首先,请注意 WebBrowser.DocumentText 是静态的,它保留原始内容,没有任何 DOM/AJAX 更改。要获取实际的当前 HTML,请在您的后台线程上执行此操作:

var html = hiddenWebBrowser.Document.GetElementsByTagName("html")[0].OuterHtml;

然后您可以在 UI 线程上更新 WebBrowser 的另一个实例:

mainForm.BeginInvoke(new Action(() => mainForm.webBrowser.DocumentText = html));

请注意,BeginInvoke 是异步的,DocumentText 赋值也是如此。 DocumentCompleted 事件将在加载 HTML 时为 mainForm.webBrowser 触发。

关于c# - 如何用另一个 DocumentText 更新 DocumentText,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22820382/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com