简体   繁体   English

延迟主线程,让新线程在加载之前工作

[英]Delay the main thread and let new thread to work before from loaded

I have win form application which load some data and fill a gridview using threads. 我有win form应用程序加载一些数据并使用线程填充gridview In here the task of filling the grid take little while and therefore, at the moment it is using a separate thread to data fill task. 在这里,填充网格的任务花费的时间很少,因此,此刻它正在使用单独的线程进行数据填充任务。 So currently what happens is windows form initially load with the some information with the grid and after that it will filling the data to the grid while the user have responsive UI to play with. 因此,当前发生的情况是Windows窗体最初在网格中加载了一些信息,此后它将在用户具有响应UI的同时将数据填充到网格中。

In form load 形式加载

DataBind();
var newThread = new Thread(new ThreadStart(FillGrid));
newThread.Start();

This FillGrid() method will each row and all the columns and depending on the value it will change the cell color and will add some data. FillGrid()方法将每一行和所有列,并根据值更改单元格颜色并添加一些数据。 What I am trying to achieve is rather than load the form with empty data, I would like to fill like half of the grid and continue filling the rest of grid after form loaded. 我要实现的目标不是用空数据加载表单,而是要填充网格的一半,并在表单加载后继续填充其余网格。 I tried like using Thread.Sleep() after calling the newThread.Start() but didn't do what I expected. 在调用newThread.Start() Thread.Sleep()之后,我尝试像使用Thread.Sleep() ,但是没有达到我的预期。

Any help on achieving this!!! 任何帮助实现这一目标!!!

And to access the gridview safely I refer to this article about Updating Your Form from Another Thread without Creating Delegates for Every Type of Update 为了安全地访问gridview请参阅本文,涉及从另一个线程更新表单而不为每种类型的更新创建委托的情况。

Thanks 谢谢

As already stated use BackgroundWorker.ReportProgress. 如前所述,使用BackgroundWorker.ReportProgress。 But you will need to not continue to update the object you send back half way (see second link). 但是您将不需要继续更新发送回一半的对象(请参阅第二个链接)。

With that said look at what is causing the grid to fill slowly. 这样,看看是什么导致网格缓慢填充。 Sending back 1/2 the data is only going to help a bit. 发送回1/2数据只会有所帮助。 How much time are you really going to save just loading 1/2 the data? 仅加载1/2的数据,您实际上将节省多少时间? Now you have two UI refreshes so the total time is longer. 现在,您有两次UI刷新,因此总时间更长。

enter link description here 在此处输入链接说明

enter link description here 在此处输入链接说明

Use an AutoResetEvent - have the main thread wait and when you have half filled the grid; 使用AutoResetEvent-让主线程等待,当网格填满一半时; signal the main thread to procede.. 通知主线程继续进行。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx http://msdn.microsoft.com/zh-CN/library/system.threading.autoresetevent.aspx

You should fill your grid while reading the data. 读取数据时,应填充网格。 Read the data in the secondary thread, then notify the UI thread when there's a chunk of data ready to be populated in the grid. 读取辅助线程中的数据,然后在网格中准备填充大量数据时通知UI线程。 You'll need to do a little thread juggling, because the UI needs to be updated from the main thread, but it shouldn't be too hard. 您需要做一些线程变戏法,因为需要从主线程更新UI,但这应该不会太难。

You can also try to use a BackgroundWorker , and update the grid in its ProgressChanged event. 您也可以尝试使用BackgroundWorker ,并在其ProgressChanged事件中更新网格。

In the background thread, do not touch the grid. 在后台线程中,请勿触摸网格。 Instead, use it only too fill your data somewhere, to some collection NOT BOUND to the grid. 取而代之的是,仅将数据填充到某个位置,而不填充到网格中。

Create Timer and in it's event PULL data from the collection that is filled in the background thread to the GUI. 创建Timer,并在事件中从后台线程填充到GUI的集合中提取数据。

That way, you won't have to worry about Invoke and all kinds of problems that you get into when talking to GUI from non-gui threads. 这样,您就不必担心Invoke以及从非GUI线程与GUI进行对话时遇到的各种问题。

Here is a really simple example using a background worker. 这是一个使用后台工作者的非常简单的示例。 I hope it points you in the right direction. 我希望它能为您指明正确的方向。

Please notice how I used the the Me.Invoke() method to update the UI. 请注意我如何使用Me.Invoke()方法更新UI。 This is required because all UI elements must be updated from the thread that created them. 这是必需的,因为必须从创建它们的线程更新所有UI元素。

Public Class Form1
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        BackgroundWorker1.RunWorkerAsync()
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim r As New Random()
        For index As Integer = 0 To 100
            Me.Invoke(Sub()
                          ListBox1.Items.Add(Guid.NewGuid().ToString())
                      End Sub)
            Threading.Thread.Sleep(r.Next(50, 300))
        Next
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Me.Invoke(Sub()
                      MsgBox("Task Complete", MsgBoxStyle.OkOnly, "Task Complete")
                  End Sub)
    End Sub
End Class

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM