1


我已经创建了一个带有线程的应用程序(这是我的第一个线程应用程序)
我有一个 WPF,单击按钮将打开一个 Excel 获取 ProductID 并在网站中搜索它并返回一些详细信息(如果它存在
)我已经创建并且它是工作正常。
但在 UI 中,我想显示一个进度条和我正在搜索的当前产品,
所以我使用线程进行了尝试。
即使在此之后,我的用户界面也冻结了。谁能帮帮我

这是我在WPF中点击的代码

private void btnSubmt_Click(object sender, RoutedEventArgs e)
    {
        ValidateWork obj = new ValidateWork();
        obj.notifyCompleteEvent += new EventHandler(obj_notifyCompleteEvent);
        obj.updateUI += new EventHandler<NotifyEventArgs>(obj_updateUI);

        if (string.IsNullOrEmpty(TxtbxFlePth.Text))
        {
            MessageBox.Show("Please Select a Excel File to Validate");
            return;
        }
        Excel.Application exclCrtApp = new Excel.Application();
        Excel.Workbook exclWrkBuk = exclCrtApp.Workbooks.Open(TxtbxFlePth.Text, ReadOnly: true);
        Excel.Worksheet exclWrkSht =( Excel.Worksheet) exclWrkBuk.Worksheets[1];
        PrgrsBar.Maximum = exclWrkSht.Range[exclWrkSht.Range["A2"], exclWrkSht.Range["A1048576"].End[Excel.XlDirection.xlUp]].Rows.Count;
        obj.fnStrt(exclWrkSht);

        string strSaveName = exclWrkBuk.FullName.ToString();
        strSaveName = strSaveName.Substring(0, strSaveName.IndexOf(".xls"));
        exclCrtApp.DisplayAlerts = false;
        exclWrkBuk.SaveAs(strSaveName+"_output.xlsx");
        exclWrkBuk.Close(false);
        exclCrtApp.DisplayAlerts = true;
        exclCrtApp.Quit();
        exclCrtApp = null;
    }


这是我的班级,它有脚步声并完成所有工作

class ValidateWork
{
    bool blnBrwRedy = false;
    public event EventHandler notifyCompleteEvent;      //event hander to notify the completion
    public event EventHandler<NotifyEventArgs> updateUI;    //event handler to notify UI for progress

    ManualResetEvent resumeUI = new ManualResetEvent(false);
    //first program the click calls
    public void fnStrt(Excel.Worksheet exclWksPass) 
    {
        Thread Trailtrd = new Thread(() => fnValidate(exclWksPass));            
        Trailtrd.SetApartmentState(ApartmentState.STA);
        Trailtrd.Name = "classfuncallthread";
        Trailtrd.Start();
        resumeUI.WaitOne();            
    }

    //worker thread
    public void fnValidate(Excel.Worksheet exclWksPass)
    {
        Excel.Range exclRngManHdr, exclRngCrtRow, exclRngOutUrl,exclRngAllPrd;
        string strGoglLnk = "https://www.newark.co.in/search?q=";
        StringBuilder strbldSrcRes = new StringBuilder();
        byte[] bytBuffResp=new byte[8192];
        string[] strResltUrl=new string[4];

        exclRngManHdr = exclWksPass.Range[exclWksPass.Range["A1"], exclWksPass.Range["VI1"].End[Excel.XlDirection.xlToLeft]];
        exclRngOutUrl = exclWksPass.Range["VI1"].End[Excel.XlDirection.xlToLeft].Offset[0,1];
        exclRngAllPrd = exclWksPass.Range[exclWksPass.Range["A2"], exclWksPass.Range["A1048576"].End[Excel.XlDirection.xlUp]];

        foreach (Excel.Range exclRngEchRow in exclRngAllPrd)
        {
            onupdateUI(exclRngEchRow.Row);
            string strSrchQry, strSupWeb = "";
            strSrchQry = exclRngEchRow.Text ;
            strSupWeb = exclRngEchRow.Offset[0, 2].Text.ToString();
            if(strSupWeb.Length>4)
            {
                strSupWeb = strSupWeb.Substring(strSupWeb.IndexOf("www") + 4);
            }

            WebBrowser webBrwser = new WebBrowser();
            webBrwser.ScriptErrorsSuppressed = true;

            webBrwser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrwser_DocumentCompleted);
            webBrwser.Navigate(strGoglLnk+strSrchQry+"+"+ exclRngEchRow.Offset[0, 1].Text);

            do
            {
                //as using the web forms browser using doevents
                System.Windows.Forms.Application.DoEvents();
            } while (webBrwser.ReadyState != WebBrowserReadyState.Complete);

            strResltUrl = webResltSerch(webBrwser, strSupWeb.ToUpper(), strSrchQry);
            while (strResltUrl == null || (strResltUrl[0].Contains("Part Not Found")))
            {
                strSrchQry = ModifedInput(strSrchQry) ;
                if (strSrchQry.Length < 6) { break; }
                webBrwser.Navigate(strGoglLnk + strSrchQry+ "+" + exclRngEchRow.Offset[0, 1].Text);
                do
                {
                    System.Windows.Forms.Application.DoEvents();
                } while (webBrwser.ReadyState != WebBrowserReadyState.Complete);
                strResltUrl = webResltSerch(webBrwser, strSupWeb.ToUpper(), strSrchQry);

            }//while loop
            exclWksPass.Cells[exclRngEchRow.Row, exclRngOutUrl.Column].Value = strResltUrl[0];
            exclWksPass.Cells[exclRngEchRow.Row, exclRngOutUrl.Column+1].Value = strResltUrl[1];
            exclWksPass.Cells[exclRngEchRow.Row, exclRngOutUrl.Column+2].Value = strResltUrl[2];
            exclWksPass.Cells[exclRngEchRow.Row, exclRngOutUrl.Column + 3].Value = strResltUrl[3];
            webBrwser.Dispose();
            webBrwser = null;
        }

        if (notifyCompleteEvent != null)
        {
            notifyCompleteEvent(this,EventArgs.Empty);
        }
        resumeUI.Set();
    }

    void webBrwser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        WebBrowser crntBrws = sender as WebBrowser;
        if (crntBrws.ReadyState==WebBrowserReadyState.Complete)
        { 
            blnBrwRedy = true;
            System.Diagnostics.Debug.Print("Loaded page " + crntBrws.Url.AbsolutePath); 
        }

    }


    private void onupdateUI(long CrntPrgrs)
    {
        var handler = updateUI;
        if (handler != null)
        {
            handler(this, new NotifyEventArgs(CrntPrgrs));
        }
    }

    public string[] webResltSerch(WebBrowser brwser,string OrigUrl,string OrgPrtnumb)

    {
        //searching the website
    }
}

UI更新没有问题进度条显示完全更新(冻结后返回时)
但窗口为空白

4

2 回答 2

1

它仍然冻结的原因是因为您要求 UI 等到ManualResetEvent设置完成。

UI 线程将停止在您的WaitOne()行,直到您设置事件,导致一切锁定。

我会考虑BackgroundWorker改用;支持进度指示,并允许您Excel.Worksheet像当前一样通过您的。如果您需要 UI 仍然响应,请不要等待TrailtrdUI 线程上的线程。

BackgroundWorker是带有进度指示的一个很好的示例。

于 2013-05-30T10:46:57.727 回答
0

您要求您的 UI 线程通过调用来等待新的验证线程完成resumeUI.WaitOne();

您在创建时已经有了正确的想法notifyCompleteEvent并且您已经注册了它,您所要做的就是删除 resumeUI.WaitOne() 调用并在 obj_updateUI eventHandler 中完成日志记录

- - - -编辑 - - - - -

public void fnStrt(Excel.Worksheet exclWksPass) 
{
    Thread Trailtrd = new Thread(() => fnValidate(exclWksPass));            
    Trailtrd.SetApartmentState(ApartmentState.STA);
    Trailtrd.Name = "classfuncallthread";
    Trailtrd.Start();                  
}

private void btnSubmt_Click(object sender, RoutedEventArgs e)
    {
        ValidateWork obj = new ValidateWork();
        obj.notifyCompleteEvent += new EventHandler(obj_notifyCompleteEvent);
        obj.updateUI += new EventHandler<NotifyEventArgs>(obj_updateUI);

        if (string.IsNullOrEmpty(TxtbxFlePth.Text))
        {
            MessageBox.Show("Please Select a Excel File to Validate");
            return;
        }
        Excel.Application exclCrtApp = new Excel.Application();        
        Excel.Worksheet exclWrkSht = // get the relevant worksheet

        //if you are always working on a single worksheet then just handle it as a data member  other wise add it to notifyCompleteEvent as an argument

    obj.fnStrt(exclWrkSht);

}

现在何时调用事件处理程序

void obj_notifyCompleteEvent()
{

  // DO your UI logic here 
  // note no need to use the dispatcher

  //now its time to save 
  string strSaveName = exclWrkBuk.FullName.ToString();
  strSaveName = strSaveName.Substring(0, strSaveName.IndexOf(".xls"));
  exclCrtApp.DisplayAlerts = false;
  exclWrkBuk.SaveAs(strSaveName+"_output.xlsx");
  exclWrkBuk.Close(false);
  exclCrtApp.DisplayAlerts = true;
  exclCrtApp.Quit();
  exclCrtApp = null;


}
于 2013-05-30T11:27:53.310 回答