I’m using WatiN to parse my web site. I have a button that starts the process. I open a browser window and navigate where I need to go, then I create a new task that calls a method called DoWork.
My problem is that if I call a new method at the end of DoWork to do something else I get strange results when I try to have the program navigate my website, however, if I don’t call this new method from DoWork and just hook the new method up to a button click all works fine. So my question is am I not properly calling my new method from the background process method, Dowork?
Code:
IE browser = new IE("http://www.mywebsite.com/");
string startYear;
string endYear;
int NumRows;
Task myThread;
public Form1()
{
InitializeComponent();
}
private void Start_Click(object sender, EventArgs e)
{
startYear = txtStartYear.Text;
endYear = txtEndYear.Text;
//website navigation work removed for brevity
browser.Button(Find.ById("ContentPlaceHolder1_btnApplyFilter")).Click();
int numRows = browser.Div(Find.ById("scroller1")).Table(Find.First()).TableRows.Count -1;
NumRows = numRows;
lblTotalRows.Text = numRows.ToString();
myThread = Task.Factory.StartNew(() => DoWork());
}
public void DoWork()
{
List<string> myList = new List<string>(NumRows);
txtStartYear.Text = startYear;
txtEndYear.Text = endYear;
for (int i = 1; i < NumRows; i++)
{
TableRow newTable = browser.Div(Find.ById("scroller1")).Table(Find.First()).TableRows[i];
string coll = string.Format("{0},{1},{2},{3},{4}", newTable.TableCells[0].Text, newTable.TableCells[1].Text, newTable.TableCells[2].Text, newTable.TableCells[3].Text, newTable.TableCells[4].Text);
myList.Add(coll);
label1.Invoke((MethodInvoker)delegate
{
label1.Text = i.ToString();
});
}
//database work removed for brevity.
browser.Button(Find.ById("btnFilter")).Click();
newMethod();
}
public void newMethod()
{
int start = int.Parse(startYear);
start++;
startYear = start.ToString();
int end = int.Parse(endYear);
end++;
endYear = end.ToString();
browser.SelectList(Find.ById("selStartYear")).SelectByValue(startYear);
browser.SelectList(Find.ById("selEndYear")).SelectByValue(endYear);
//removed for brevity
}
}
To reiterate, if I call newMethod from Dowork the line browser.SelectList(Find.ById("selStartYear")).SelectByValue(startYear) doesn’t behave properly, but if I remove the call to newMethod from Dowork and just hook newMethod up to a button it works fine. I’m wondering if it has to do with DoWork being a background task?
When I say it doesn’t behave properly I mean that when you select an item from the drop down list the page auto posts back, however the above line of code selects it but the page doesn’t post back, which shouldn’t be possible. If I don’t call the method within DoWork I don’t have this issue.
You’re modifying a UI element from a non-UI thread. You’ve already got code which deals with that within DoWork, via
Control.Invoke– you need to do the same kind of thing fornewMethod. It would probably be easiest just to invoke the whole method in the UI thread:(I’m using
label.BeginInvokeas I’m not sure whether the browser itself is a “normal” control – but usinglabelwill get to the right thread anyway. Ifbrowser.BeginInvokecompiles, that would be clearer.)