Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使我的主代码/窗体等待另一个类';函数在C#中完成,而不冻结?_C#_Multithreading_Function_Class_Webbrowser Control - Fatal编程技术网

如何使我的主代码/窗体等待另一个类';函数在C#中完成,而不冻结?

如何使我的主代码/窗体等待另一个类';函数在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

我有一个从SQL中提取字符串/url的代码,然后我的代码如下:

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查询,这就是为什么我变成一个类来同时使用多个实例。啊,好的,我很抱歉。埃夫克的答案可能更适合你。是的,它工作得很完美,完全符合我的计划。不过,也谢谢你!它工作得很好,非常感谢你。这正是我所需要的,一个函数可以进行“回调”。