【问题标题】:Working with WCF and task-based operations使用 WCF 和基于任务的操作
【发布时间】:2013-12-13 07:36:11
【问题描述】:

我试图让客户端可以同时进行多个搜索,而不会影响搜索页面的响应时间。为此,我希望在 WCF 中使用 .NET 4.5 的基于任务的操作,但我无法理解其逻辑。

我希望我的最终结果是对 WCF API 进行多次调用,然后将它们合并为一个大结果并按每个搜索项相关性对其进行排序。

这就是我今天的代码的样子:

public partial class WebForm1 : System.Web.UI.Page
{
    private static SwepubSearchServiceClient _client;
    private static List<SearchItem> _searchItems = new List<SearchItem>(); 
    protected void Page_Load(object sender, EventArgs e)
    {
        _client = new SwepubSearchServiceClient();

        var result1 = GetAsyncSearchItems("query1", "subQuery1");
        var result2 = GetAsyncSearchItems("query2", "subQuery2");
        var result3 = GetAsyncSearchItems("query3", "subQuery3");

        // What to do here?

    }

    private static async Task<SearchItem[]> GetAsyncSearchItems(string query = "", string subQuery = "")
    {
        var task = _client.DoSearchSimpleAsync(query, subQuery);
        return await task;
    }
}

基本上,我需要知道的是在我取回每个结果(result1、result2、result3)后如何处理它们。我虽然我将能够在每次方法调用之后调用 result1.Result 但到那时它们还没有被计算所以它不会有任何好处。

虽然我在 GetAsyncSearchItems 方法看起来像这样之前尝试了一些东西:

private static async void GetAsyncSearchItems()
    {
        var task1 = _client.DoSearchSimpleAsync("query1", "subQuery1");
        var task2 = _client.DoSearchSimpleAsync("query2", "subQuery2");
        var task3 = _client.DoSearchSimpleAsync("query3", "subQuery3");

        var result1 = await task1;
        var date1 = DateTime.Now.TimeOfDay;
        var result2 = await task2;
        var date2 = DateTime.Now.TimeOfDay;
        var result3 = await task3;
        var date3 = DateTime.Now.TimeOfDay;

        var list = new List<SearchItem>();
        list.AddRange(result1);
        list.AddRange(result2);
        list.AddRange(result3);
    }

当我这样做时,我能够在列表对象中检索结果,但我无法将其返回给我的 Page_Load,因为异步方法只能返回 void、Task 或 Task,所以它没有用。 还是我误解了什么?我应该在静态方法中使用结果吗?

我可能在这里遗漏了一些基本的东西,但我希望有人能引导我朝着正确的方向前进。我真的很乐意!

【问题讨论】:

    标签: c# asp.net .net wcf asynchronous


    【解决方案1】:

    您的GetAsyncSearchItems 方法应如下所示(在Task-based Asynchronous Pattern 之后):

    private static async Task<List<SearchItem>> GetSearchItemsAsync()
    {
        var task1 = _client.DoSearchSimpleAsync("query1", "subQuery1");
        var task2 = _client.DoSearchSimpleAsync("query2", "subQuery2");
        var task3 = _client.DoSearchSimpleAsync("query3", "subQuery3");
    
        var results = await Task.WhenAll(task1, task2, task3);
    
        var list = new List<SearchItem>();
        list.AddRange(results[0]);
        list.AddRange(results[1]);
        list.AddRange(results[2]);
        return list;
    }
    

    一旦你有了那个方法,你就可以这样写Page_Load

    protected async void Page_Load(object sender, EventArgs e)
    {
        _client = new SwepubSearchServiceClient();
        var results = await GetSearchItemsAsync();
        ...
    }
    

    虽然async void 在这种情况下有效,但您使用RegisterAsyncTask 的ASP.NET 团队RegisterAsyncTask,如下所示:

    protected void Page_Load(object sender, EventArgs e)
    {
        _client = new SwepubSearchServiceClient();
        RegisterAsyncTask(new PageAsyncTask(PageLoadAsync));
    }
    
    private async Task PageLoadAsync()
    {
        var results = await GetSearchItemsAsync();
        ...
    }
    

    您可能会发现我的async intro 很有帮助。

    【讨论】:

    • 哦,实际上我刚刚意识到我无法在 GetSearchItemsAsync 方法中返回 SearchItems 列表,因为这不是 void、Task 或 Task
    【解决方案2】:

    这样做的“.NET 4.5 方式”as discussed in this Q&A 是让您的Page_Load 方法async。然后你可以调用你的async 方法,ASP.NET 将把剩下的交给客户端:

    protected async void Page_Load(object sender, EventArgs e)
    {
        ...
        var results = await GetAsyncSearchItems(...)
        ... do something with the results
    }
    
    private static async SearchItem[] GetAsyncSearchItems()
    {
        ... await stuff
        return list;
    }
    

    更多资源:

    【讨论】:

      【解决方案3】:

      你可以这样做:

          var task1 = _client.DoSearchSimpleAsync("query1", "subQuery1");
          var task2 = _client.DoSearchSimpleAsync("query2", "subQuery2");
          var task3 = _client.DoSearchSimpleAsync("query3", "subQuery3");
      
          await Task.WhenAll(task1, task2, task3);
      
          var result1 = task1.Result;
          var date1 = DateTime.Now.TimeOfDay;
          var result2 = task2.Result;
          var date2 = DateTime.Now.TimeOfDay;
          var result3 = task3.Result;
          var date3 = DateTime.Now.TimeOfDay;
      

      【讨论】:

        【解决方案4】:

        您需要将您的三个结果,result1、result2 和 result3 添加到任务数组中。

        那么你可以这样做:

        Task.WaitAll(任务);

        其中 tasks 是数组。

        http://msdn.microsoft.com/en-us/library/dd270695(v=vs.110).aspx

        WaitAll 完成后,您可以从每个任务中检索 SearchItems 的列表。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-12-14
          • 1970-01-01
          • 2013-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多