【问题标题】:Web service call takes too longWeb 服务调用耗时过长
【发布时间】:2017-05-12 13:07:12
【问题描述】:

我用 C# 创建了一个客户端 Web 服务,以便能够检索我从服务器获取的一本书的信息。

当我调用从我传入参数的 bookIds 获取书籍信息时,有时调用速度很快,有时需要 1 分钟,有时需要很长时间。我只将 bookIds 存储在我的数据库中,所以当我需要有关书籍的更多信息(标题、发布日期等)时,我会联系 webService 以获取它们。我正在使用 chrome 调试器并在“网络”选项卡下,我只有 “注意;请求尚未完成”...没有其他可以帮助我的信息看看到底发生了什么! -

我调用的函数是getBooksByAuthor(authorId),我应该只有8个与authorId相关的结果,所以它不应该花那么长时间!这是我所有的代码:

public async Task<T> GetObject<T>(string uriActionString)
        {
            T wsObject =
                default(T);
            try
            {
                using (var client = new HttpClient())
                {
                    client.BaseAddress = new Uri(@"https://books.server.net");
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    // connect to the server
                    var byteArray = Encoding.ASCII.GetBytes("NXXXXX:Passxxxx");
                    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

                    HttpResponseMessage response = await client.GetAsync(uriActionString);
                    response.EnsureSuccessStatusCode();
                    wsObject = JsonConvert.DeserializeObject<T>(await((HttpResponseMessage)response).Content.ReadAsStringAsync());
                }
                return wsObject;
            }
            catch (Exception e)
            {
                throw (e);
            }
        }

        public async Task<Book> viewBook(int id)
        {
            Book book = new Book();
            string urlAction = String.Format("api/book/{0}", id);
            book = await GetWSObject<Book>(urlAction);

            return book;
        }

        public string getBooksByAuthor (int authorId) {

            string result = "";

            var books = from a in db.Authors
                        where a.id == authorId
                        select new
                        {
                            id = a.id
                        };

            foreach (var book in books.ToList())
            {
                var bookdata = await ws.viewBook(book .id);
                result += this.getBookObject(book.id).name + ", ";   
            }

            return result;
        }

     /* How to return a string from a task ? */  
    foreach (var author in listOfAuthors)
      {
      booksFromAuthors.Add(new { id = author.id, book = getBooksByAuthor(author.id) // ? how convert it to a string ?  });
      }

【问题讨论】:

  • 使用调试器或分析器怎么样?
  • 不要使用.Result。您的方法是异步的,因此请正确使用 await
  • @Uwe Keim,我使用 chrome 调试器,在“网络”选项卡下,我只有“注意;请求尚未完成”...没有其他信息!
  • 服务器端分析
  • 是的,在通话中使用await 并放弃.Result。你所描述的发生是一个僵局。永远不要在 asp.net 上下文中使用 .Result

标签: c# web-services


【解决方案1】:

失去 getBookObject 函数,你只是在那里开始一个新任务使事情复杂化。

如果您使该函数异步,您可以简单地等待 getBooksByAuthor 的结果。

public async Task<Book> getBook(int id)
{
    string urlAction = String.Format("api/book/{0}", id);
    return await GetWSObject<Book>(urlAction);
}

public async Task<string> getBooksByAuthor (int authorId) 
{
    string result = "";

    var books = from a in db.Authors
                where a.id == authorId
                select new
                {
                    id = a.id
                };

    foreach (var book in books.ToList())
    {
        var bookdata = await this.getBook(book.id);
        result += bookdata.name + ", ";   
    }

    return result; 
}

如果要并发http请求,可以创建多个Task,使用Task.WhenAll,例如

https://stackoverflow.com/a/30668277/1538039

【讨论】:

  • 删除 getBookObject 不会解决我遇到的问题。但我会看看 Task.WhenAll 解决方案。谢谢
  • 我更新了我的代码,希望你现在能更好地理解我的需求。
  • 使 getBooksByAuthor 异步任务 ,然后等待它。
  • 我想我最终别无选择!谢谢。顺便说一句,我想投票+1,我投票-1 !!。我必须等待 1 小时才能更改它。您可以编辑您的答案(通过放置空格或其他内容)以便我再次投票吗?欢呼
猜你喜欢
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2013-02-26
相关资源
最近更新 更多