C# 填充网格时跨线程操作无效

C# 填充网格时跨线程操作无效,c#,multithreading,C#,Multithreading,我正在尝试从匿名类型实例列表填充网格。我想应用线程,因为这会使我的应用程序在填充结果时冻结。但我一直在犯这样的错误: 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; }

我正在尝试从匿名类型实例列表填充网格。我想应用线程,因为这会使我的应用程序在填充结果时冻结。但我一直在犯这样的错误:

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;
}
public-Thread{get;private-set;}
公共字符串搜索{get;set;}
公共字符串searchCity{get;set;}
公共字符串searchState{get;set;}
私有无效爬网()
{
如果(CheckForInternetConnection())
{
if(string.IsNullOrEmpty(search)| string.IsNullOrEmpty(search)| string.IsNullOrEmpty(searchCity)| string.IsNullOrWhiteSpace(searchCity)| string.IsNullOrEmpty(searchState)| string.IsNullOrWhiteSpace(searchState))
{
MessageBox.Show(“请填写搜索标准”);
}
其他的
{
字符串url=string.Format(“http://www.yellowpages.com/{0}/酒店?g={1}&q={2}”,搜索城市,搜索城市,搜索);
如果(!isURLExist(url))
{
MessageBox.Show(“未找到任何记录。请重试”);
}
其他的
{
Pages htmlDoc=新页面(url);
htmlDoc.pageResults();
string searchUrl=string.Empty;
对于(int ii=1;ii新{Address=a,Name=n})
.Zip(城市,(p,c)=>新{p.地址,p.名称,城市=c})
.Zip(State,(q,s)=>新{q.地址,q.名称,q.城市,State=s})
.Zip(Zip,(r,z)=>新{r.地址,r.名称,r.城市,r.州,Zip=z})
.Zip(电话,(t,p)=>新{t.姓名,t.地址,t.城市,t.州,t.Zip,电话=p})
.Zip(网站,(u,w)=>新{u.名称,地址,城市,州,邮编,电话,网站=w})
.ToList();
int rowCount=gridHotelDetails.Rows.Count;
foreach(完整信息中的var详细信息)
{
//此行中发生错误
gridHotelDetails.Rows.Add(rowCount++,detail.Name,detail.Address,detail.City,detail.State,detail.Zip,detail.Phone,detail.Website);
}
}
}
UseWaitCursor=false;
}
}
其他的
{
MessageBox.Show(“互联网连接不可用”);
}
}
私有无效btnSearch_单击(对象发送者,事件参数e)
{
search=txtSearch.Text.Trim();
searchCity=txtCity.Text.Trim();
searchState=ddState.Text.Trim();
MyThread=新线程(新线程开始(爬网));
MyThread.Start();
gridHotelDetails.Visible=true;
}

为什么会发生此错误?如何解决此错误?

您不能从创建ui控件的线程以外的线程对其进行更改。请参阅本文,了解如何实现您的目标的示例:


简短的回答是,当您从非UI线程更新UI元素时,需要在UI元素上使用Invoke。按钮单击和处理程序通常不在UI线程上

任何名为
invokererequired
的UI元素上都应该有一个属性。如果这是真的,您需要使用Invoke传递一个委托来完成您想要在该UI元素上完成的工作。如果为false,您可以直接设置属性(因为您在UI线程上)

所以类似这样的情况(尽管您希望将此检查从foreach循环中去掉,因为它在执行期间不会更改,而且只会浪费周期检查):


你的问题是什么?(附言:“标准”是“标准”的复数形式。)@O.R.Mapper:我已经更新了我的问题。“请看一看。你在使用WinForms还是WPF?”问了很多次。这似乎是所有其他人都被标记为复制对象的家长:不用担心!欢迎来到SO。这只是我今天单独看到的这个问题的第三个例子,实际上我没有在这里花那么多时间。:)
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);
    });
}