如何为 List<T> 应用异步和等待?

Posted

技术标签:

【中文标题】如何为 List<T> 应用异步和等待?【英文标题】:how to apply async and await for List<T>? 【发布时间】:2019-12-18 19:05:29 【问题描述】:

我想异步显示项目列表,我正在执行如下操作,但我不确定它是否正常工作。你们能帮帮我吗,这是正确的方法吗?

private List<SuggestedItemsInput> SuggestedItemAsync()

   OHDWebService OHDService = new OHDWebService();
   List<SuggestedItemsInput> suggestedItemsList = OHDService.SaveSuggestedItems(hdnPlainBody.Value, hfdOrderRecordID.Value);
   return suggestedItemsList;


private async void GetSuggestedItemsFromService()

   Task<List<SuggestedItemsInput>> task = new Task<List<SuggestedItemsInput>>(SuggestedItemAsync);
   task.Start();
   List<SuggestedItemsInput> suggestedItems = await task;
   ViewState["sItems"] = suggestedItems;
   if (suggestedItems != null && suggestedItems.Count > 0)
   
       GetSuggestedItems(Request["OrderRecordID"].ToString());
       lblInfo.Text = string.Empty;
   

编辑: 现在我使用下面的代码它正在工作,我正在通过 SaveAndGetSuggestedItem() 方法保存和获取数据。将数据保存在数据库中需要时间,同时我想在完成后显示加载图像加载图像应该隐藏并且数据应该填充在网格视图中,我在下面添加了代码,但问题是网格视图手动刷新页面后会加载,加载图片会持续显示。

    /// <summary>
    /// Gets the SuggestedItems from API.
    /// </summary>
    private List<SuggestedItemsInput> SaveAndGetSuggestedItem()
    
        try
        
            OHDWebService OHDService = new OHDWebService();
            return OHDService.SaveSuggestedItems(hdnPlainBody.Value, hfdOrderRecordID.Value);
        
        catch (Exception ex)
        

            throw ex;
        
    

    /// <summary>
    /// Async call to the SuggestedItems.
    /// </summary>
    private async Task GetSuggestedItemsAsync()
    
        try
        

            LoadingImg.Visible = true;
            List<SuggestedItemsInput> suggestedItems = await Task.Run(() => SaveAndGetSuggestedItemFromKenome());
            LoadingImg.Visible = false;

            ViewState["sItems"] = suggestedItems;
            if (suggestedItems != null && suggestedItems.Count > 0)
            
                BindSuggestedItems(hfdOrderRecordID.Value);
                lblInfo.Text = string.Empty;
            
        
        catch (Exception ex)
        

            throw ex;
        
    

首页(查看):

 <asp:Panel ID="LoadingImg" runat="server" Visible="false">
                            <i class="fa fa-spinner fa-pulse fa-3x fa-fw" style="color: darkblue"></i>
                            <span class="sr-only">Loading...</span><span>Please wait...</span>
                        </asp:Panel>
                        <asp:Label ID="lblInfo" runat="server"></asp:Label>
                        <asp:GridView ID="grdSuggestedItems" runat="server" CellPadding="4" CellSpacing="4" AutoGenerateColumns="false" Width="100%" CssClass="table" HorizontalAlign="Center">
                            <HeaderStyle HorizontalAlign="Center" BackColor="#8b6f4e" ForeColor="white" />
                            <Columns>
                                <asp:BoundField HeaderText="Matched Text" DataField="MessageText" />
                                <asp:TemplateField HeaderText="ItemId">
                                    <ItemTemplate>
                                        <div>
                                            <span style="font-size: 12px;">
                                                <a target="_blank" style="cursor: pointer" href='<%= ConfigurationManager.AppSettings["InvInquiry"].ToString() %><%#Eval("ItemID") %>'><%#Eval("ItemID") %></a>
                                            </span>
                                            <div style="font-size: 10px;">
                                                <%#Eval("ItemDescription") %>
                                            </div>
                                        </div>
                                    </ItemTemplate>
                                </asp:TemplateField>
                                <asp:BoundField HeaderText="ProductLine" DataField="ProductLine" />
                                <asp:BoundField HeaderText="Qty" DataField="Qty" />
                                <asp:BoundField HeaderText="Confidence(%)" DataField="Confidence" />
                                <asp:BoundField HeaderText="Rank" DataField="Rank" />
                            </Columns>
                            <RowStyle HorizontalAlign="Center" />
                        </asp:GridView>

【问题讨论】:

您希望在这里发生什么?顺便说一句,除非您正在编写事件处理程序,否则不要使用 async void 我的整个页面有很多回发事件,因为我想异步加载gridview。在单击事件 GetSuggestedItemsFromService 上,此方法将调用并保存数据,之后我会将其绑定到 gridview。这将花费大约 20 到 30 秒,所以如果应用 asyn await 我可以同时做其他工作 你看microsoft guide了吗?我认为您可以通过首先阅读一些文章和教程来了解async/await。此外,在提出问题时,请包括当前正在发生的事情以及您希望发生的事情。 私有异步 void GetSuggestedItemsFromService()-> 私有异步任务 GetSuggestedItemsFromService() 如果你把OHDService.SaveSuggestedItems(...)也设为异步会更好 【参考方案1】:

好的,有几件事。

您的SuggestedItemAsync 方法不是异步的,它返回多个项目,因此应将其称为SuggestedItems。由于最好了解它与“SuggestedItems”的关系什么,我还可以考虑在前面添加Get,就像使用其他方法一样。所以GetSuggestedItems 将是我选择的名称。 请勿使用async void,除非您将该方法用作事件处理程序(向后兼容)。如果没有返回类型,请改用async Task。 您的 GetSuggestedItemsFromService 方法是异步的,因此您应该将其命名为 GetSuggestedItemsFromServiceAsync。 我不知道OHDWebService 是什么,但您应该检查它是否实现了IDisposable,如果是,请将其包装在using-statement 中。

我假设您只想启动方法SuggestedItems asnychronouly,因为它需要很长时间。您可以使用Task.Run 来做到这一点,这比显式创建新任务要好得多。

以下是我将如何重写您的代码:

private List<SuggestedItemsInput> GetSuggestedItems()

    OHDWebService OHDService = new OHDWebService();
    return OHDService.SaveSuggestedItems(hdnPlainBody.Value, hfdOrderRecordID.Value);


private async Task GetSuggestedItemsFromServiceAsync()

    List<SuggestedItemsInput> suggestedItems = await Task.Run(() => GetSuggestedItems());

    ViewState["sItems"] = suggestedItems;
    if (suggestedItems != null && suggestedItems.Count > 0)
    
        GetSuggestedItems(Request["OrderRecordID"].ToString());
        lblInfo.Text = string.Empty;
    

编辑: 因此,在经历了一些 cmets 之后,还有一些事情要提。

GetSuggestedItems 方法似乎还保存了一些值,因此SaveSuggestedItemsSaveAndGetSuggestedItems 可能是更合适的名称。 GetSuggestedItems 方法使用未定义的hdnPlainBody(或者您没有显示代码所在的位置)。你的意思是让它成为一个参数吗?如果是这样,它必须是一些具有Value 属性的类/结构。但是在GetSuggestedItemsFromServiceAsync 方法中,您可以使用string 作为参数调用GetSuggestedItems 方法。是否存在接受 string 的重载,但您没有向我们展示?

最后是实际问题。我将在此处包含您的评论,这很清楚我们在谈论什么:

SuggestedItemAsync 将保存数据并返回列表,但是当光标进入 await 时,它不允许运行下一行,但数据保存在 db 中。

我从中得到的是,您希望数据的插入和获取以异步方式逐行进行。 为此,OHDService.SaveSuggestedItems 的实现必须是 async 并支持它。在您的代码中,它不是async,因此您可以逐行实现此行为的唯一方法是迭代您正在输入的数据并异步执行此操作,一次插入一行。不幸的是,您没有为我提供足够的背景信息来帮助您。 另外,由于您提到它已经花费了(太)长的时间,因此将其包装为异步可能不是一个好主意,因为它将花费更长的时间。

我认为您确实应该提供更多信息。我们真的无法帮助您,因为:

您调用了一个以string 作为参数的无参数方法,但没有提及任何相关内容 您没有指定预期的行为(请参阅我的第一条评论) 您使用了一些从未在您显示的代码中定义的变量 (hdnPlainBody)

还有你的其他评论,我不太明白。

.. 我已经添加了面板,我已经添加了 img,并且我在“列出建议的项目”之前和之后显示和隐藏加载图像,只有 true 在加载可见 false 后才有效,否则不会触发

我现在将留下这个答案,因为我相信它对你有一些有价值的信息。但是,我知道这并不能完全回答您的问题。请澄清其他内容和/或提出新问题。确保包含所有我们需要重现问题的代码并包含您想要发生的事情。

祝你好运!

最终编辑:

现在您已经更新了问题并添加了新代码,我可以再次查看它。老实说,我有点迷路了。

您现在调用了一个名为 SaveAndGetSuggestedItemFromKenome 的方法,但该方法并不存在。 您仍然没有显示任何关于 hdnPlainBodyhfdOrderRecordID 的信息,这两者都从未在您的代码中定义。 您现在有 try-catch 语句,在这种情况下它实际上没有意义。这仍然是一种可能性,但我建议您阅读this question。

另外,很抱歉,我无法理解您对问题的描述:

问题是grid-view会在手动刷新页面后加载,并且加载图像连续显示。

我认为最好仔细阅读我告诉你的所有内容,调整你的代码并用该代码提出一个新问题。以易于理解的方式详细解释问题所在。这意味着当前的行为是什么以及您所期望的。 提供尽可能多的相关信息。

【讨论】:

GetSuggestedItems() 不接受该参数,并且您将参数作为GetSuggestedItems(Request["OrderRecordID"].ToString()); 传递。 原来的SuggestedItemAsync 调用SaveSuggestedItems,所以我不确定把Get 放在前面会完全清楚它的作用。它似乎做了一个 Save 来返回已保存内容的列表,我不会将其描述为 Get 操作。 SuggestedItemAsync 将保存数据并返回列表, 但是当光标进入等待它不允许运行下一行但数据保存在数据库中。我已经添加了面板,我已经添加了 img,并且我在“ListSuggestedItems”之前和之后显示和隐藏加载图像,只有 true 在加载可见 false 之后才有效 @User_4373 很好,我错过了那个。 @PeterB 它显然返回数据,所以 get 不是一个糟糕的选择。当然,如果是SaveAndGet 或类似的东西会更好,但我对此一无所知OHDService

以上是关于如何为 List<T> 应用异步和等待?的主要内容,如果未能解决你的问题,请参考以下文章

如何为绑定到 List<T> 的 dataGridView 设置 columnNames?

Java 如何为 List<Car> 构建 SQL SELECT 语句?

如何为 List<Class name> 创建 JSONArray

如何为ListBox项提供有意义的名称

如何取消异步等待

如何为 List<List<List<Integer>>> nums = new ArrayList<List<List<Integer>&