C# 线程 dataGridView 和加载
我试图加载一个 dataGridView,这需要一些时间,所以我想出了一个隐藏 datagridview 的想法,并在顶部放置一个图像,上面写着“正在加载...”完成后,图像消失,数据网格重新出现。我尝试使用线程来做到这一点,但没有运气。
有人可以告诉我我是否以正确的方式处理这个问题?
Label loadingText = new Label();
PictureBox loadingPic = new PictureBox();
private void TelephoneDirectory_Load(object sender, EventArgs e)
{
dataGridView1.Visible = false;
Thread i = new Thread(LoadImage);
i.Start();
Thread t = new Thread(LoadData);
t.Start();
}
void LoadImage()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(LoadImage));
}
else
{
loadingPic.Image = Properties.Resources.ReportServer;
loadingPic.Location = new Point(0, 0);
loadingPic.Name = "loadingPic";
loadingPic.Dock = DockStyle.Fill;
loadingPic.SizeMode = PictureBoxSizeMode.CenterImage;
loadingText.Text = "Loading, please wait...";
loadingText.Name = "loadingText";
loadingText.TextAlign = ContentAlignment.MiddleCenter;
loadingText.Size = new Size(this.Size.Width, 30);
loadingText.Font = new System.Drawing.Font("Segoe UI", 9);
loadingText.Location = new Point(0, (this.Size.Height / 2 + 10));
this.Controls.AddRange(new Control[] { loadingPic, loadingText });
loadingText.BringToFront();
}
}
private void LoadData()
{
if (dataGridView1.InvokeRequired)
{
dataGridView1.Invoke(new MethodInvoker(this.LoadData));
}
else
{
DirectorySearcher sea = null;
DirectoryEntry dir = null;
DirectoryEntry d = null;
string domainname = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name;
domainname = domainname.Replace(".", ",DC=");
try
{
dir = new DirectoryEntry();
dir.Path = "LDAP://DC=" + domainname;
sea = new DirectorySearcher(dir);
sea.Filter = "(&(objectClass=user)(extensionAttribute1=1)(telephoneNumber=*))";
sea.PageSize = 2000;
SearchResultCollection res = sea.FindAll();
foreach (SearchResult result in res)
{
//DO ALL MY STUFF
dataGridView1.Rows.Add(row);
}
}
catch { }
LoadDataComplete();
}
}
void LoadDataComplete()
{
PictureBox loadingGraphic = this.Controls["loadingPic"] as PictureBox;
Label LoadingLabel = this.Controls["loadingText"] as Label;
DataGridView dataGrid = this.Controls["dataGridView1"] as DataGridView;
dataGrid.Visible = true;
LoadingLabel.Visible = false;
LoadingLabel.Dispose();
loadingGraphic.Visible = false;
loadingGraphic.Dispose();
dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
dataGridView1.ClearSelection();
}
Im trying to load a dataGridView which takes some time, so ive come up with an idea of hiding the datagridview and put an image over the top which says Loading... when finished, the image goes away and the datagrid reappears. Ive tried to do this using threading but having no luck.
Can somebody tell me if i am approaching this in the right way?
Label loadingText = new Label();
PictureBox loadingPic = new PictureBox();
private void TelephoneDirectory_Load(object sender, EventArgs e)
{
dataGridView1.Visible = false;
Thread i = new Thread(LoadImage);
i.Start();
Thread t = new Thread(LoadData);
t.Start();
}
void LoadImage()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(LoadImage));
}
else
{
loadingPic.Image = Properties.Resources.ReportServer;
loadingPic.Location = new Point(0, 0);
loadingPic.Name = "loadingPic";
loadingPic.Dock = DockStyle.Fill;
loadingPic.SizeMode = PictureBoxSizeMode.CenterImage;
loadingText.Text = "Loading, please wait...";
loadingText.Name = "loadingText";
loadingText.TextAlign = ContentAlignment.MiddleCenter;
loadingText.Size = new Size(this.Size.Width, 30);
loadingText.Font = new System.Drawing.Font("Segoe UI", 9);
loadingText.Location = new Point(0, (this.Size.Height / 2 + 10));
this.Controls.AddRange(new Control[] { loadingPic, loadingText });
loadingText.BringToFront();
}
}
private void LoadData()
{
if (dataGridView1.InvokeRequired)
{
dataGridView1.Invoke(new MethodInvoker(this.LoadData));
}
else
{
DirectorySearcher sea = null;
DirectoryEntry dir = null;
DirectoryEntry d = null;
string domainname = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name;
domainname = domainname.Replace(".", ",DC=");
try
{
dir = new DirectoryEntry();
dir.Path = "LDAP://DC=" + domainname;
sea = new DirectorySearcher(dir);
sea.Filter = "(&(objectClass=user)(extensionAttribute1=1)(telephoneNumber=*))";
sea.PageSize = 2000;
SearchResultCollection res = sea.FindAll();
foreach (SearchResult result in res)
{
//DO ALL MY STUFF
dataGridView1.Rows.Add(row);
}
}
catch { }
LoadDataComplete();
}
}
void LoadDataComplete()
{
PictureBox loadingGraphic = this.Controls["loadingPic"] as PictureBox;
Label LoadingLabel = this.Controls["loadingText"] as Label;
DataGridView dataGrid = this.Controls["dataGridView1"] as DataGridView;
dataGrid.Visible = true;
LoadingLabel.Visible = false;
LoadingLabel.Dispose();
loadingGraphic.Visible = false;
loadingGraphic.Dispose();
dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
dataGridView1.ClearSelection();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为此生成线程可能不是最好的主意,您可以使用 ThreadPool 或 BackgroundWorker
加载图像应该是足够快,您可以同步执行,因此请确保在实际需要之前确实需要在另一个线程上执行一些操作。
问自己这样的问题:如果实际上我的图像比我的数据表加载得晚怎么办? (“但每次我检查时它加载得更快”在谈论线程时不是一个有效的参数)
在方法的开头,您使用
.Invoke
这基本上意味着“等待 UI 线程并调用我的同步编码”,这会轰炸你的整个想法。尝试这样的事情:
.Invoke
.Invoke()
伪代码可能如下所示:
Spawning threads for this might not be the best idea, you could use ThreadPool or BackgroundWorker
Loading image should be fast enough that you could just do it synchronously, so make sure you actually need to do some operation on the other thread before you actually need it.
Ask yourself questions like: what if actually my image will load later then my dataTable? ("but it loads faster every time I checked" is not an valid argument when talking about threads)
At the beginning of your methods you are using
.Invoke
which basically means "wait for UI thread and invoke my code on it synchronously" which bombards your whole idea.Try something like this:
.Invoke
.Invoke()
Pseudocode coud look like this: