这是我的要求:
在按钮上单击我需要从数据库获取数据并填入datagridview,我正在使用一个函数。由于检索可能需要很长时间,并且我想同时使用UI,我希望此功能在单独的线程中运行。
为此,我正在使用异步回调。但是在begininvoke()
和endinvoke()
函数之间。我不是在写任何代码(我不知道要写什么来让UI响应)。
datagridview正在正确填充,但是当我在函数检索数据时尝试访问它时,UI被阻止。
答案 0 :(得分:1)
我建议不从UI线程启动长时间运行的操作。首先启动另一个线程,然后在该单独的线程中执行长时间运行的操作。完成后,使用Form.Invoke()方法将结果发布回UI。这样,UI线程不会直接受到影响。
您可以使用像BackgroundWorker这样的构造。
,而不是手动创建另一个线程如果从UI线程开始长时间运行操作,则需要定期调用Application.DoEvents()(例如在循环内)。但是,如果长时间运行操作是IO密集型操作 - 这意味着您大多数时间都在等待IO操作 - 那么您将无法根据需要随时调用Application.DoEvents()。这将使UI看起来不那么敏感或不稳定。正如我上面提到的,单独的线程在这方面是更好的方法。
答案 1 :(得分:0)
如果您使用loop
填充DataGridView
,则可以使用Application.DoEvents()
内的方法loop
让您的用户界面保持响应状态DataGridView
。
正如你所说的问题不是循环,我认为最好的方法是使用BackgroundWorker
类。
您可以在[{1}}
的DataGridView
事件中填充DoWork()
的位置
您可以在代码BackgroundWorker
活动期间开始BackgroundWorker.DoWork()
活动!
答案 2 :(得分:0)
首先,我应该在UI表单本身创建asynccallback函数,而不是在中间级别,在我的例子中是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