C# 异步填充ASP.NET ListBox而不阻塞UI

C# 异步填充ASP.NET ListBox而不阻塞UI,c#,asp.net,multithreading,.net-3.5,backgroundworker,C#,Asp.net,Multithreading,.net 3.5,Backgroundworker,我在ASP.NET用户控件中有一个列表框,我想用从数据库检索到的潜在较大的列表来填充该列表框(最多50k个项目)。由于正在填充列表框(在页面加载事件中),我不想阻止UI。使用同步代码,直到列表框填充完成后,才会显示页面: List<string> items = GetItemsFromDB(); foreach (var item in items) // can take some time, blocks UI { if (shouldItemBeListed(

我在ASP.NET用户控件中有一个列表框,我想用从数据库检索到的潜在较大的
列表来填充该列表框(最多50k个项目)。由于正在填充列表框(在页面加载事件中),我不想阻止UI。使用同步代码,直到列表框填充完成后,才会显示页面:

List<string> items = GetItemsFromDB();    
foreach (var item in items) // can take some time, blocks UI
{
    if (shouldItemBeListed(item))
        ListBox1.Items.Add(item);
}
2。BackgroundWorker线程。比1工作得更好。(至少列表框正在更新新项目),但仍然反应迟钝

var bw = new BackgroundWorker();
bw.DoWork += (o, args) => Populate();
bw.RunWorkerAsync();

我总是可以将列表框项目分成更小的组,并根据用户的请求填充更多的内容,但这通常是如何正确实现的呢?

Damon说得对,您正在寻找ajax,这应该会为您提供所需的功能。我发现了一个使用gridview的frmo MSDN示例,但它应该是可适应的:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Enter New Employees</title>
<script runat="server">
    private List<Employee> EmployeeList;

    protected void Page_Load()
    {
        if (!IsPostBack)
        {
            EmployeeList = new List<Employee>();
            EmployeeList.Add(new Employee(1, "Jump", "Dan"));
            EmployeeList.Add(new Employee(2, "Kirwan", "Yvette"));
            ViewState["EmployeeList"] = EmployeeList;
        }
        else
            EmployeeList = (List<Employee>)ViewState["EmployeeList"];

        EmployeesGridView.DataSource = EmployeeList;
        EmployeesGridView.DataBind();
    }

    protected void InsertButton_Click(object sender, EventArgs e)
    {
        if (String.IsNullOrEmpty(FirstNameTextBox.Text) ||
           String.IsNullOrEmpty(LastNameTextBox.Text)) { return; }

        int employeeID = EmployeeList[EmployeeList.Count-1].EmployeeID + 1;

        string lastName = Server.HtmlEncode(FirstNameTextBox.Text);
        string firstName = Server.HtmlEncode(LastNameTextBox.Text);

        FirstNameTextBox.Text = String.Empty;
        LastNameTextBox.Text = String.Empty;

        EmployeeList.Add(new Employee(employeeID, lastName, firstName));
        ViewState["EmployeeList"] = EmployeeList;

        EmployeesGridView.DataBind();
        EmployeesGridView.PageIndex = EmployeesGridView.PageCount;
    }

    protected void CancelButton_Click(object sender, EventArgs e)
    {
        FirstNameTextBox.Text = String.Empty;
        LastNameTextBox.Text = String.Empty;
    }

    [Serializable]
    public class Employee
    {
        private int _employeeID;
        private string _lastName;
        private string _firstName;

        public int EmployeeID
        {
            get { return _employeeID; }
        }

        public string LastName
        {
            get { return _lastName; }
        }

        public string FirstName
        {
            get { return _firstName; }
        }

        public Employee(int employeeID, string lastName, string firstName)
        {
            _employeeID = employeeID;
            _lastName = lastName;
            _firstName = firstName;
        }
    }

</script>
</head>
<body>
<form id="form1" runat="server">
<div>
    &nbsp;</div>
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"      />
    <table>
        <tr>
            <td style="height: 206px" valign="top">
                <asp:UpdatePanel ID="InsertEmployeeUpdatePanel" runat="server"     UpdateMode="Conditional">
                    <ContentTemplate>
                      <table cellpadding="2" border="0" style="background-    color:#7C6F57">
                        <tr>
                          <td><asp:Label ID="FirstNameLabel" runat="server"     AssociatedControlID="FirstNameTextBox" 
                                         Text="First Name" ForeColor="White" /></td>
                          <td><asp:TextBox runat="server" ID="FirstNameTextBox" /></td>
                        </tr>
                        <tr>
                          <td><asp:Label ID="LastNameLabel" runat="server"     AssociatedControlID="LastNameTextBox" 
                                         Text="Last Name" ForeColor="White" /></td>
                          <td><asp:TextBox runat="server" ID="LastNameTextBox" /></td>
                        </tr>
                        <tr>
                          <td></td>
                          <td>
                            <asp:LinkButton ID="InsertButton" runat="server"     Text="Insert" OnClick="InsertButton_Click" ForeColor="White" />
                            <asp:LinkButton ID="Cancelbutton" runat="server"     Text="Cancel" OnClick="CancelButton_Click" ForeColor="White" />
                          </td>
                        </tr>
                      </table>
                      <asp:Label runat="server" ID="InputTimeLabel"><%=DateTime.Now %>    </asp:Label>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </td>
            <td style="height: 206px" valign="top">
                <asp:UpdatePanel ID="EmployeesUpdatePanel" runat="server"     UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:GridView ID="EmployeesGridView" runat="server"     BackColor="LightGoldenrodYellow" BorderColor="Tan"
                             BorderWidth="1px" CellPadding="2" ForeColor="Black"     GridLines="None" AutoGenerateColumns="False">
                            <FooterStyle BackColor="Tan" />
                            <SelectedRowStyle BackColor="DarkSlateBlue"     ForeColor="GhostWhite" />
                            <PagerStyle BackColor="PaleGoldenrod"     ForeColor="DarkSlateBlue" HorizontalAlign="Center" />
                            <HeaderStyle BackColor="Tan" Font-Bold="True" />
                            <AlternatingRowStyle BackColor="PaleGoldenrod" />
                            <Columns>
                                <asp:BoundField DataField="EmployeeID"     HeaderText="Employee ID" />
                                <asp:BoundField DataField="LastName" HeaderText="Last     Name" />
                                <asp:BoundField DataField="FirstName" HeaderText="First     Name" />
                            </Columns>
                            <PagerSettings PageButtonCount="5" />
                        </asp:GridView>
                        <asp:Label runat="server" ID="ListTimeLabel"><%=DateTime.Now %>    </asp:Label>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="InsertButton"     EventName="Click" />
                    </Triggers>
                </asp:UpdatePanel>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

输入新员工
私人名单雇员名单;
受保护的无效页面加载()
{
如果(!IsPostBack)
{
EmployeeList=新列表();
添加(新员工(1,“跳转”、“跳转”);
新增(新员工(2名,“Kirwan”、“Yvette”);
ViewState[“员工列表”]=员工列表;
}
其他的
EmployeeList=(列表)视图状态[“EmployeeList”];
EmployeesGridView.DataSource=EmployeeList;
EmployeesGridView.DataBind();
}
受保护的void InsertButton_单击(对象发送方,事件参数e)
{
if(String.IsNullOrEmpty(FirstNameTextBox.Text)||
String.IsNullOrEmpty(LastNameTextBox.Text)){return;}
int employeeID=EmployeeList[EmployeeList.Count-1].employeeID+1;
字符串lastName=Server.HtmlEncode(FirstNameTextBox.Text);
字符串firstName=Server.HtmlEncode(LastNameTextBox.Text);
FirstNameTextBox.Text=String.Empty;
LastNameTextBox.Text=String.Empty;
添加(新员工(employeeID,lastName,firstName));
ViewState[“员工列表”]=员工列表;
EmployeesGridView.DataBind();
EmployeesGridView.PageIndex=EmployeesGridView.PageCount;
}
受保护的作废取消按钮\u单击(对象发送者,事件参数e)
{
FirstNameTextBox.Text=String.Empty;
LastNameTextBox.Text=String.Empty;
}
[可序列化]
公营雇员
{
私人国际雇员ID;
私有字符串_lastName;
私有字符串_firstName;
公共国际雇员ID
{
获取{return\u employeeID;}
}
公共字符串姓氏
{
获取{return\u lastName;}
}
公共字符串名
{
获取{return\u firstName;}
}
公共雇员(int employeeID、字符串lastName、字符串firstName)
{
_employeeID=employeeID;
_lastName=lastName;
_名字=名字;
}
}

Damon说得对,因为您正在寻找ajax,它应该为您提供所需的功能。我发现了一个使用gridview的frmo MSDN示例,但它应该是可适应的:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Enter New Employees</title>
<script runat="server">
    private List<Employee> EmployeeList;

    protected void Page_Load()
    {
        if (!IsPostBack)
        {
            EmployeeList = new List<Employee>();
            EmployeeList.Add(new Employee(1, "Jump", "Dan"));
            EmployeeList.Add(new Employee(2, "Kirwan", "Yvette"));
            ViewState["EmployeeList"] = EmployeeList;
        }
        else
            EmployeeList = (List<Employee>)ViewState["EmployeeList"];

        EmployeesGridView.DataSource = EmployeeList;
        EmployeesGridView.DataBind();
    }

    protected void InsertButton_Click(object sender, EventArgs e)
    {
        if (String.IsNullOrEmpty(FirstNameTextBox.Text) ||
           String.IsNullOrEmpty(LastNameTextBox.Text)) { return; }

        int employeeID = EmployeeList[EmployeeList.Count-1].EmployeeID + 1;

        string lastName = Server.HtmlEncode(FirstNameTextBox.Text);
        string firstName = Server.HtmlEncode(LastNameTextBox.Text);

        FirstNameTextBox.Text = String.Empty;
        LastNameTextBox.Text = String.Empty;

        EmployeeList.Add(new Employee(employeeID, lastName, firstName));
        ViewState["EmployeeList"] = EmployeeList;

        EmployeesGridView.DataBind();
        EmployeesGridView.PageIndex = EmployeesGridView.PageCount;
    }

    protected void CancelButton_Click(object sender, EventArgs e)
    {
        FirstNameTextBox.Text = String.Empty;
        LastNameTextBox.Text = String.Empty;
    }

    [Serializable]
    public class Employee
    {
        private int _employeeID;
        private string _lastName;
        private string _firstName;

        public int EmployeeID
        {
            get { return _employeeID; }
        }

        public string LastName
        {
            get { return _lastName; }
        }

        public string FirstName
        {
            get { return _firstName; }
        }

        public Employee(int employeeID, string lastName, string firstName)
        {
            _employeeID = employeeID;
            _lastName = lastName;
            _firstName = firstName;
        }
    }

</script>
</head>
<body>
<form id="form1" runat="server">
<div>
    &nbsp;</div>
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"      />
    <table>
        <tr>
            <td style="height: 206px" valign="top">
                <asp:UpdatePanel ID="InsertEmployeeUpdatePanel" runat="server"     UpdateMode="Conditional">
                    <ContentTemplate>
                      <table cellpadding="2" border="0" style="background-    color:#7C6F57">
                        <tr>
                          <td><asp:Label ID="FirstNameLabel" runat="server"     AssociatedControlID="FirstNameTextBox" 
                                         Text="First Name" ForeColor="White" /></td>
                          <td><asp:TextBox runat="server" ID="FirstNameTextBox" /></td>
                        </tr>
                        <tr>
                          <td><asp:Label ID="LastNameLabel" runat="server"     AssociatedControlID="LastNameTextBox" 
                                         Text="Last Name" ForeColor="White" /></td>
                          <td><asp:TextBox runat="server" ID="LastNameTextBox" /></td>
                        </tr>
                        <tr>
                          <td></td>
                          <td>
                            <asp:LinkButton ID="InsertButton" runat="server"     Text="Insert" OnClick="InsertButton_Click" ForeColor="White" />
                            <asp:LinkButton ID="Cancelbutton" runat="server"     Text="Cancel" OnClick="CancelButton_Click" ForeColor="White" />
                          </td>
                        </tr>
                      </table>
                      <asp:Label runat="server" ID="InputTimeLabel"><%=DateTime.Now %>    </asp:Label>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </td>
            <td style="height: 206px" valign="top">
                <asp:UpdatePanel ID="EmployeesUpdatePanel" runat="server"     UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:GridView ID="EmployeesGridView" runat="server"     BackColor="LightGoldenrodYellow" BorderColor="Tan"
                             BorderWidth="1px" CellPadding="2" ForeColor="Black"     GridLines="None" AutoGenerateColumns="False">
                            <FooterStyle BackColor="Tan" />
                            <SelectedRowStyle BackColor="DarkSlateBlue"     ForeColor="GhostWhite" />
                            <PagerStyle BackColor="PaleGoldenrod"     ForeColor="DarkSlateBlue" HorizontalAlign="Center" />
                            <HeaderStyle BackColor="Tan" Font-Bold="True" />
                            <AlternatingRowStyle BackColor="PaleGoldenrod" />
                            <Columns>
                                <asp:BoundField DataField="EmployeeID"     HeaderText="Employee ID" />
                                <asp:BoundField DataField="LastName" HeaderText="Last     Name" />
                                <asp:BoundField DataField="FirstName" HeaderText="First     Name" />
                            </Columns>
                            <PagerSettings PageButtonCount="5" />
                        </asp:GridView>
                        <asp:Label runat="server" ID="ListTimeLabel"><%=DateTime.Now %>    </asp:Label>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="InsertButton"     EventName="Click" />
                    </Triggers>
                </asp:UpdatePanel>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

输入新员工
私人名单雇员名单;
受保护的无效页面加载()
{
如果(!IsPostBack)
{
EmployeeList=新列表();
添加(新员工(1,“跳转”、“跳转”);
新增(新员工(2名,“Kirwan”、“Yvette”);
ViewState[“员工列表”]=员工列表;
}
其他的
EmployeeList=(列表)视图状态[“EmployeeList”];
EmployeesGridView.DataSource=EmployeeList;
EmployeesGridView.DataBind();
}
受保护的void InsertButton_单击(对象发送方,事件参数e)
{
if(String.IsNullOrEmpty(FirstNameTextBox.Text)||
String.IsNullOrEmpty(LastNameTextBox.Text)){return;}
int employeeID=EmployeeList[EmployeeList.Count-1].employeeID+1;
字符串lastName=Server.HtmlEncode(FirstNameTextBox.Text);
字符串firstName=Server.HtmlEncode(LastNameTextBox.Text);
FirstNameTextBox.Text=String.Empty;
LastNameTextBox.Text=String.Empty;
添加(新员工(employeeID,lastName,firstName));
ViewState[“员工列表”]=员工列表;
EmployeesGridView.DataBind();
EmployeesGridView.PageIndex=EmployeesGridView.PageCount;
}
受保护的作废取消按钮\u单击(对象发送者,事件参数e)
{
FirstNameTextBox.Text=String.Empty;
LastNameTextBox.Text=String.Empty;
}
[可序列化]
公营雇员
{
私人国际雇员ID;
私有字符串_lastName;
私有字符串_firstName;
公共int雇员
<select id='ddl' onchange='document.getElementById("<%= hidValue.ClientID %>").value=this.value'>
    <option value=''>Loading...</option>
</select>
<asp:Hidden runat='server' id='hidValue' />

$(function(){
   $.ajax("... your api endpoit").then(function(result){
       var items = result.items; // actual implementation will change
       var ddl = $(ddl);
       ddl.html(''); // remove the 'loading' option.
       foreach(var item in items) {
           var option = $("<option>");
           option.attr("value",item.value);
           option.text(item.text);
           ddl.append(option);
       }    
   });
});