我正在尝试从匿名类型实例列表中填充网格。我想应用线程,因为这会使我的应用程序在填充结果时冻结。但我不断收到这个错误:
list of anonymous type instances Control 'gridHotelDetails' accessed from a thread other than the thread it was created on.
我已经标记了发生错误的行。我的代码:
public Thread MyThread { get; private set; }
public string search { get; set; }
public string searchCity { get; set; }
public string searchState { get; set; }
private void crawl()
{
if (CheckForInternetConnection())
{
if (string.IsNullOrEmpty(search) || string.IsNullOrEmpty(search) || string.IsNullOrEmpty(searchCity) || string.IsNullOrWhiteSpace(searchCity) || string.IsNullOrEmpty(searchState) || string.IsNullOrWhiteSpace(searchState))
{
MessageBox.Show("Please fill up the search criterias");
}
else
{
string url = string.Format("http://www.yellowpages.com/{0}/hotels?g={1}&q={2}", searchCity, searchCity, search);
if (!isURLExist(url))
{
MessageBox.Show("No records found. Please try again.");
}
else
{
Pages htmlDoc = new Pages(url);
htmlDoc.pageResults();
string searchUrl = string.Empty;
for (int ii = 1; ii <= 1; ii++)
{
searchUrl = url + "&page=" + ii;
htmlDoc.findHotels(searchUrl);
List<string> Name = htmlDoc.Names;
List<string> Address = htmlDoc.Address;
List<string> City = htmlDoc.City;
List<string> State = htmlDoc.State;
List<string> Zip = htmlDoc.Zip;
List<string> Phone = htmlDoc.Phone;
List<string> Website = htmlDoc.Website;
var CompleteInformation = Name.Zip(Address, (n, a) => new { Address = a, Name = n })
.Zip(City, (p, c) => new { p.Address, p.Name, City = c })
.Zip(State, (q, s) => new { q.Address, q.Name, q.City, State = s })
.Zip(Zip, (r, z) => new { r.Address, r.Name, r.City, r.State, Zip = z })
.Zip(Phone, (t, p) => new { t.Name, t.Address, t.City, t.State, t.Zip, Phone = p })
.Zip(Website, (u, w) => new { u.Name, u.Address, u.City, u.State, u.Zip, u.Phone, Website = w })
.ToList();
int rowCount = gridHotelDetails.Rows.Count;
foreach (var detail in CompleteInformation)
{
// Error occuring in this line
gridHotelDetails.Rows.Add(rowCount++, detail.Name, detail.Address, detail.City, detail.State, detail.Zip, detail.Phone, detail.Website);
}
}
}
UseWaitCursor = false;
}
}
else
{
MessageBox.Show("Internet Connection Not Available");
}
}
private void btnSearch_Click(object sender, EventArgs e)
{
search = txtSearch.Text.Trim();
searchCity = txtCity.Text.Trim();
searchState = ddState.Text.Trim();
MyThread = new Thread(new ThreadStart(crawl));
MyThread.Start();
gridHotelDetails.Visible = true;
}
为什么会出现此错误?如何解决此错误?
答案 0 :(得分:1)
您无法从创建的线程以外的线程更改ui控件。请参阅此文章以获取如何完成所需内容的示例:
Trying to change UI control property from different thread using . InvokeRequired
答案 1 :(得分:1)
简短的回答是,当您从非UI线程更新它们时,需要在UI元素上使用Invoke。按钮点击和处理程序通常不在UI线程上。
任何名为InvokeRequired
的UI元素都应该有一个属性。如果是这样,则需要使用Invoke传递委托以完成您要在该UI元素上完成的工作。如果它是假的,你可以直接设置属性(因为你在UI线程上)。
所以类似(虽然你会想要从foreach循环中取出这个检查,因为它在执行期间不会改变,你只是浪费周期检查):
if (!gridHotelDetails.InvokeRequired)
{
gridHotelDetails.Rows.Add(rowCount++, detail.Name, detail.Address, detail.City, detail.State, detail.Zip, detail.Phone, detail.Website);
}
else
{
gridHotelDetails.Invoke(() =>
{
gridHotelDetails.Rows.Add(rowCount++, detail.Name, detail.Address, detail.City, detail.State, detail.Zip, detail.Phone, detail.Website);
});
}