我用线程创建了一个应用程序(这是我的第一个线程应用程序)
我有一个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更新后进度条显示完全更新(冻结后返回)时没有问题 但窗口是空白的
答案 0 :(得分:1)
它仍然冻结的原因是因为你要求用户界面等到ManualResetEvent
被设置。
UI线程将停在您的WaitOne()
行,直到您设置事件,导致所有内容锁定。
我考虑使用BackgroundWorker
代替;支持进度指示,并允许您通过当前正在进行的Excel.Worksheet
。如果您需要UI仍然响应,请不要等待UI线程上的Trailtrd
线程。
Here's一个带有进度指示的BackgroundWorker
的好例子。
答案 1 :(得分:0)
您要求您的UI线程通过调用resumeUI.WaitOne();
等待新的验证线程完成
当你创建notifyCompleteEvent
并且已经注册了它时,你已经有了正确的想法,你所要做的就是删除resumeUI.WaitOne()调用并在obj_updateUI eventHandler中完成日志记录
<强> ------- EDIT --------- 强>
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;
}