2012-01-09 31 views
1

我正在使用Windows應用程序,其中我有一個tabControl,其中用戶可以像IE一樣打開多個選項卡。現在我必須訪問選定的選項卡,然後必須對打開的文檔執行一些操作。從線程訪問和更改winform webbrowser

我能夠訪問,但訪問選定的選項卡,並執行操作後

應用成爲當我使用另一個線程來執行這個任務掛起。

請建議我該怎麼做。

我正在使用.net 4.0。 C#

請參見下面的代碼,這個代碼在按鈕上單擊

TextToSpeechThread = new Thread(new ThreadStart(ReadWebDocument)); 
     TextToSpeechThread.Name = ApplicationManager.GlobalThreadNaming.TextToSpeech.ToString(); 
     TextToSpeechThread.SetApartmentState(ApartmentState.STA); 
     TextToSpeechThread.Start(); 

這是線程方法調用操作

browserTabControl.Invoke(new MethodInvoker(delegate 
     { 

      browserTabControl.SelectedTab.Controls[0].Invoke(new MethodInvoker(delegate 
      { 
       WebBrowser _browser = (WebBrowser)(browserTabControl.SelectedTab.Controls[0]); 

       my_Voice.Speak(_browser.DocumentTitle.ToString(), my_Spflag); 

       foreach (var link in _browser.Document.All) 
       { 
        HtmlElement elem = (HtmlElement)(link); 
        Thread tempThread = new Thread(new ParameterizedThreadStart(HighlightingWebDocument)); 
        tempThread.Start(elem); 

        if (elem.TagName == "A") 
        { 
         if (elem.InnerText != null) 
         { 
          if (elem.InnerText.ToString() != "") 
          { 
           my_Voice.Speak(elem.InnerText.ToString(), my_Spflag); 
          } 
         } 
        } 
        if (elem.TagName == "DIV") 
        { 
         if (elem.InnerText != null) 
         { 
          if (elem.InnerText.ToString() != "") 
          { 
           my_Voice.Speak(elem.InnerText.ToString(), my_Spflag); 
          } 
         } 
         //my_Voice.Speak(elem.TagName.ToString(), my_Spflag); 
        } 
        if (elem.TagName == "IFRAME") 
        { 
         if (elem.InnerText != null) 
         { 
          if (elem.InnerText.ToString() != "") 
          { 
           my_Voice.Speak(elem.InnerText.ToString(), my_Spflag); 
          } 
         } 
        } 
        if (elem.TagName == "SPAN") 
        { 
         if (elem.InnerText != null) 
         { 
          if (elem.InnerText.ToString() != "") 
          { 
           my_Voice.Speak(elem.InnerText.ToString(), my_Spflag); 
          } 
         } 
        } 
        if (elem.TagName == "LINK") 
        { 
         if (elem.InnerText != null) 
         { 
          if (elem.InnerText.ToString() != "") 
          { 
           my_Voice.Speak(elem.InnerText.ToString(), my_Spflag); 
          } 
         } 
        } 
        if (elem.TagName == "INPUT") 
        { 
         if (elem.InnerText != null) 
         { 
          if (elem.InnerText.ToString() != "") 
          { 
           my_Voice.Speak(elem.InnerText.ToString(), my_Spflag); 
          } 
         } 

        } 
        Thread.Sleep(150); 
       } 
      })); 


     })); 

現在請大家提供一些有用的鏈接...

這是你們提出的另一種方法..

聲明委託

delegate void HighlightBrowsercontent(HtmlElement elem); 
    HighlightBrowsercontent highLightBrowsercontent = null; 

在窗體加載

public Form1() 
    { 
     InitializeComponent(); 

     // initialise the delegate to point to an implemntation 

     highLightBrowsercontent = new HighlightBrowsercontent(OnHighLightContent); 

    } 

在點擊按鈕上,我想讀出的內容以及要突出顯示的鏈接。

private void button1_Click(object sender, EventArgs e) 
    { 
     HtmlElementCollection links = webBrowser1.Document.Links; 

     this.backgroundWorker2.RunWorkerAsync(links); 
    } 

最後這個過程我想執行。

private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) 
    { 
     IAsyncResult res = BeginInvoke(myEnableCancel, new object[] { true }); 
     ReadDocumetnAsync((HtmlElementCollection)(e.Argument)); 
     BeginInvoke(myEnableCancel, new object[] { false }); 
    } 

    void ReadDocumetnAsync(HtmlElementCollection elemCollection) 
    { 
     foreach (var elem in elemCollection) 
     { 
      HtmlElement elem1 = (HtmlElement)(elem); 

      SpeechLib.SpVoice myVoice = new SpeechLib.SpVoice(); ; 
      if (elem1.InnerText != null) 
      { 
       BeginInvoke(highLightBrowsercontent, elem); 
       myVoice.Speak(elem1.InnerText); 
       System.Threading.Thread.Sleep(450); 

       IAsyncResult ar = BeginInvoke(highLightBrowsercontent, elem);// Update the screen 
       // Wait until the folder has been created before proceeding with the content of the folde 
       while (!ar.IsCompleted) 
       { 
        Application.DoEvents(); 
        ar.AsyncWaitHandle.WaitOne(-1, false); 
       } 


      } 

     } 

    } 
public void OnHighLightContent(HtmlElement element) 
    { 
     HtmlDocument doc2 = webBrowser1.Document as HtmlDocument; 
     toolStripStatusLabel2.Text = element.OuterHtml; 
     element.Focus(); 
     element.ScrollIntoView(false); 
     StringBuilder html = new StringBuilder(doc2.Body.OuterHtml); 
     String substitution = "<span style='background-color: rgb(255, 255, 0);'>" + element.OuterHtml + "</span>"; 
     html.Replace(element.OuterHtml, substitution); 
     doc2.Body.InnerHtml = html.ToString(); 
    } 

它是隻讀取第一個鏈接。 我不知道這是怎麼回事..

+1

您嘗試過的任何代碼示例,例外文本或屏幕截圖可以更好地描述問題? – 2012-01-09 11:38:10

+0

我沒有收到錯誤,當我嘗試運行它時,它只是變得不正常。其實我必須讀出所有的文件內容,並做到這一點,我使用一個單獨的線程,它可以找到所有的鏈接,div,跨越一切,併爲用戶讀出。它正在工作,但應用程序掛起 – Abhishek 2012-01-09 12:06:07

回答

1

不允許更改用戶界面從一個線程以外的調度線程關聯到您試圖更改的控件。您將需要使用Control.BeginInvoke來完成不同線程的更新。

+0

我使用的是建議的東西。我張貼代碼請審查。感謝回覆。 – Abhishek 2012-01-09 12:52:35

+0

@ Abhisheks.net:您是否嘗試過使用BeginInvoke而不是Invoke? – Tudor 2012-01-09 13:11:23

+0

我用它但沒有運氣,問題是一樣的。 – Abhishek 2012-01-09 13:17:32

2

由於Invoke調用,此代碼在主線程上運行,而不是您的工作線程。所以是的,當它開始運行時會阻塞UI,Speak()需要時間。使用BeginInvoke不能解決這個問題。

首先收集字符串List<string>,這不應該超過幾分之一秒。把這個清單傳給工人說話。

使用SpeakAsync()也可以工作,避免使用線程並使中斷說話變得容易得多,但要記住頁面上的位置會更困難。用迭代器順便解決了這個問題,在您最喜歡的C#語言書中查看關鍵字的產量

+0

我使用了後臺工作器,但它產生了另一個問題。我發佈了新的代碼,只是檢查它是什麼錯誤,..感謝您的建議。 – Abhishek 2012-01-10 08:51:36

+0

你根本沒有聽從我的建議。代碼看起來很糟糕,它可能會因爲例外而死亡。我不認爲我可以幫助你,祝你好運。 – 2012-01-10 12:33:20