这是我的要求:
单击按钮时,我需要从数据库中获取数据并填充到 datagridview 中,为此我使用了一个函数。由于检索可能需要很长时间并且我想同时使用 UI,我希望这个函数在单独的线程中运行。为此,我使用异步回调。但在begininvoke()
andendinvoke()
函数之间。我没有写任何代码(我不知道写什么来让 UI 响应)。
datagridview 正在正确填充,但是当我在函数检索数据时尝试访问它时 UI 被阻止。
这是我的要求:
单击按钮时,我需要从数据库中获取数据并填充到 datagridview 中,为此我使用了一个函数。由于检索可能需要很长时间并且我想同时使用 UI,我希望这个函数在单独的线程中运行。为此,我使用异步回调。但在begininvoke()
andendinvoke()
函数之间。我没有写任何代码(我不知道写什么来让 UI 响应)。
datagridview 正在正确填充,但是当我在函数检索数据时尝试访问它时 UI 被阻止。
我建议不要从 UI 线程开始长时间运行的操作。首先启动另一个线程,然后在该单独的线程中执行长时间运行的操作。完成后,使用 Form.Invoke() 方法将结果发布回 UI。这样,UI 线程不会直接受到影响。
除了手动创建另一个线程,您还可以使用BackgroundWorker之类的构造。
如果您确实从 UI 线程开始长时间运行的操作,则需要定期调用 Application.DoEvents()(例如在循环内)。但是,如果长时间运行的操作是 IO 密集型的——这意味着你大部分时间都在等待 IO 操作——那么你就不会像你想要的那样频繁地调用 Application.DoEvents()。这将使 UI 看起来反应迟钝或生涩。正如我上面提到的,单独的线程在这方面是一种更好的方法。
如果您使用 a来loop
填充您的.DataGridView
Application.DoEvents()
loop
DataGridView
正如您所说,问题不在于循环,我认为最好的方法是使用BackgroundWorker
该类。
如果发生以下情况,您可以DataGridView
在哪里填充DoWork()
BackgroundWorker
您可以在代码BackgroundWorker.DoWork()
活动期间开始活动button_click
!
首先,我应该在 UI 表单本身中创建异步回调函数,而不是在中间层,在我的例子中是 DataMgr。另外,我应该为 begininvoke 函数添加最后两个参数,并在我传递空值的地方添加适当的值。它应该是
MethodDelegate dlgt = new MethodDelegate(DataMgr.countIssuingEntities);
TempValueHolder tmp = new TempValueHolder();
AsyncCallback cb = new AsyncCallback(MyAsyncCallBack);
IAsyncResult ar = dlgt.BeginInvoke(issueGroupId, element.ControlType, (EvaluatingEntityCombo.SelectedItem as CIQHydCore.RefData.RefDataInfo).Id, (IssuingEntityCombo.SelectedItem as CIQHydCore.RefData.RefDataInfo).Id, str1, str2,**cb,dlgt**);
在 MyAsyncCallBack 函数中,我们需要使用从末尾检索到的值填充 datgridview