如何使我的主代码/窗体等待另一个类';函数在C#中完成,而不冻结?
我有一个从SQL中提取字符串/url的代码,然后我的代码如下:如何使我的主代码/窗体等待另一个类';函数在C#中完成,而不冻结?,c#,multithreading,function,class,webbrowser-control,C#,Multithreading,Function,Class,Webbrowser Control,我有一个从SQL中提取字符串/url的代码,然后我的代码如下: WebScrape browser1 = new WebScrape(); browser1.StartBrowser(weblink); richTextBox1.Text = browser1.wholeText; WebScrape browser1 = new WebScrape(); browser1.DocumentCompletedCallback = () => { // may need to re
WebScrape browser1 = new WebScrape();
browser1.StartBrowser(weblink);
richTextBox1.Text = browser1.wholeText;
WebScrape browser1 = new WebScrape();
browser1.DocumentCompletedCallback = () => {
// may need to return to UI thread here via Invoke
richTextBox1.Text = browser1.wholeText;
};
browser1.StartBrowser(weblink);
WebScrape是一个包含浏览器的类,StartBrowser启动它并将其导航到url/weblink,然后在文档完成时更新“wholeText”值
这是StartBrowser:
public void StartBrowser(string address)
{
url = address;
wb = new WebBrowser();
wb.DocumentCompleted += Web_DocumentCompleted;
wb.ScriptErrorsSuppressed = true;
Navigate(url);
}
这将转到我的导航功能以更新url
private void Navigate(String address)
{
if (String.IsNullOrEmpty(address)) return;
if (address.Equals("about:blank")) return;
if (!address.StartsWith("http://") && !address.StartsWith("https://"))
{
address = "http://" + address;
}
try
{
wb.Navigate(new Uri(address));
}
catch (System.UriFormatException)
{
return;
}
}
然后,当WebDocument完成时,将指定所需的变量,如中所示:
private void Web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
htmlCode = wb.Document;
wb.Dispose();
wholeText = getTexts();
plainText = splitText();
numberOfWords = plainText.Length;
webLinks = getLinks();
imageLinks = getImages();
imageSizes = getImageSize();
}
这里的问题是,在StartBrowser()之后,它直接进入richTextBox1.Text,而不是等待类本身完成它正在做的事情
我如何让我的代码等待我的类使用Navigate完成,并在不冻结UI/表单的情况下完成这些操作
文档完成时更新“wholeText”值
那么为什么不把richTextBox1.Text=browser1.wholeText;在您的Web_DocumentCompleted方法中
private void Web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
htmlCode = wb.Document;
wb.Dispose();
wholeText = getTexts();
plainText = splitText();
numberOfWords = plainText.Length;
webLinks = getLinks();
imageLinks = getImages();
imageSizes = getImageSize();
richTextBox1.Text = browser1.wholeText;
}
这应该解决第一个问题,但所有这些都在主线程上运行
你可以做:
Thread backgroundThread = new Thread(new ThreadStart(new Action(() => browser1.StartBrowser(weblink))));
backgroundThread.Start();
它会将StartBrowser方法移动到一个新线程,从而使Web_DocumentCompleted事件完成。我不是百分之百的相信这件事,所以也许有人能比我更清楚这件事。记住调用UI元素,因为您无法从另一个线程访问它们。直接的方法是为您的
WebScrape提供回调函数,以便在文档解析完成后调用:
public class WebScrape() {
// ...
public Action DocumentCompletedCallback;
}
private void Web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// ...
DocumentCompletedCallback?.Invoke();
}
然后在文档完成时调用它:
public class WebScrape() {
// ...
public Action DocumentCompletedCallback;
}
private void Web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// ...
DocumentCompletedCallback?.Invoke();
}
你是这样使用它的:
WebScrape browser1 = new WebScrape();
browser1.StartBrowser(weblink);
richTextBox1.Text = browser1.wholeText;
WebScrape browser1 = new WebScrape();
browser1.DocumentCompletedCallback = () => {
// may need to return to UI thread here via Invoke
richTextBox1.Text = browser1.wholeText;
};
browser1.StartBrowser(weblink);
如果需要的话,你可以用async\Wait和Tasks(更“现代”的方式)做类似的事情。WebDocumentCompleted在WebScrape类中,RichTextBox1只是用于文本,WebScrape类的实例稍后将用于SQL查询,这就是为什么我变成一个类来同时使用多个实例。啊,好的,我很抱歉。埃夫克的答案可能更适合你。是的,它工作得很完美,完全符合我的计划。不过,也谢谢你!它工作得很好,非常感谢你。这正是我所需要的,一个函数可以进行“回调”。