使用异步回调和线程机制填充datagridview

时间:2013-08-23 05:56:02

标签: c# winforms datagridview

我是.NET新手。我需要在C#winforms中使用异步回调机制完成以下赋值。

在表单加载上,我需要从数据库中获取数据并填充数据网格视图。检索可能需要很长时间,我想同时使用UI。此外,我需要一个回调机制来检查是否填充了datagridview。我必须使用线程和异步回调机制来实现这一点。

    private CustomerEntities cn = null;

    delegate CustomerEntities DataSourceDelegate();
    delegate void loadGridViewDelegate(CustomerEntities dtCustomers);

    DataSourceDelegate delegate_GetCustomers;

    public CustomerEntities DataSource()
    {
        cn = new CustomerEntities();
        return cn;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        status.Text = "Loading";
        delegate_GetCustomers = new DataSourceDelegate(DataSource);
        delegate_GetCustomers.BeginInvoke(LoadCustomerCallBack, null);
    }

    private void LoadCustomerCallBack(IAsyncResult ar)
    {
        CustomerEntities dtCutomers;
        dtCutomers = delegate_GetCustomers.EndInvoke(ar);
        loadGridView(dtCutomers);
    }

    private void loadGridView(CustomerEntities dtCutomers)
    {
        if (dataGridView.InvokeRequired)
        {
            loadGridViewDelegate del = new loadGridViewDelegate(loadGridView);
            dataGridView.Invoke(del, new CustomerEntities[] { dtCutomers });
        }
        else
        {
            dataGridView.DataSource = dtCutomers.customerDetails;
        }
    }

datagridview正在正确填充,但是当我在函数检索数据时尝试访问它时,UI被阻止。

2 个答案:

答案 0 :(得分:0)

您需要执行在主线程上修改WinForm控件的任何代码。在回调中使用此类型的模式:

private void CallbackHandler (object sender, EventArgs e)
 {
     if (InvokeRequired)
     {
         Invoke((MethodInvoker)delegate { CallbackHandler (sender, e); });
         return;
     }

     // If you get here, you are running on the main thread.
 }

编辑:对于实际的Async'获取数据',您的数据库库很可能会有一个函数接受回调作为其参数之一。这将为您处理其他所有事情。

手动处理线程只需创建一个任务:

Task.Factory.StartNew ( () =>
{
    FunctionThatTakesALongTime();
    CallbackHandler();
}

答案 1 :(得分:0)

像这样:

myWindow.BeginInvoke(new My_Main.ProductDelegate(myWindow.PopulateGrid), new object[] { row });

但是,如果您的代码在后台线程上运行,则只应使用Invoke / BeginInvoke。

如果您的UpdateProducts方法在UI线程上运行,则不需要BeginInvoke;你可以简单地调用方法,如下所示:

myWindow.PopulateGrid(row);

如果您确实调用了BeginInvoke,则需要通过在循环内移动行声明来在每次迭代中创建一个单独的数组实例。