c# - await client.GetStringAsync 无一异常(exception)退出

标签 c# asp.net .net async-await asp.net-web-api2

我正在关注这个 blog post关于如何在 ASP.NET Web API 2 中使用批处理支持。服务器代​​码似乎可以工作并监听端口 12345。

当我运行客户端代码时,它到达这一行:

dynamic listOfCustomers = JToken.Parse(await client.GetStringAsync("http://localhost:12345/api/WebCustomers"));

并在没有抛出任何异常的情况下退出。这是调试输出:

'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\12.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities.Sync\12.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\12.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'c:\users\documents\visual studio 2013\Projects\client_batch\client_batch\bin\Debug\client_batch.vshost.exe'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml.Linq\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.Linq.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Data.DataSetExtensions\v4.0_4.0.0.0__b77a5c561934e089\System.Data.DataSetExtensions.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.CSharp\v4.0_4.0.0.0__b03f5f7f11d50a3a\Microsoft.CSharp.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Net.Http\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Net.Http.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
The thread 0x1b80 has exited with code 259 (0x103).
The thread 0x1fec has exited with code 259 (0x103).
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'c:\users\mryan.asavie\documents\visual studio 2013\Projects\client_batch\client_batch\bin\Debug\client_batch.exe'. Symbols loaded.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'c:\users\mryan.asavie\documents\visual studio 2013\Projects\client_batch\client_batch\bin\Debug\Newtonsoft.Json.dll'. Cannot find or open the PDB file.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'c:\users\mryan.asavie\documents\visual studio 2013\Projects\client_batch\client_batch\bin\Debug\System.Net.Http.Formatting.dll'. Cannot find or open the PDB file.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'c:\users\mryan.asavie\documents\visual studio 2013\Projects\client_batch\client_batch\bin\Debug\Ploeh.AutoFixture.dll'. Cannot find or open the PDB file.
'client_batch.vshost.exe' (CLR v4.0.30319: client_batch.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
The thread 0x1920 has exited with code 259 (0x103).
The thread 0x14ac has exited with code 259 (0x103).
The program '[7268] client_batch.vshost.exe' has exited with code 0 (0x0).

这是服务器的代码:

namespace MyWebApp
{
    class Program {

        static void Main(string[] args)
        {
            string serviceUrl = "http://localhost:12345";
            using (WebApp.Start(serviceUrl, Configuration))
            {

                Console.WriteLine("Service listening at {0}", serviceUrl);
                Console.WriteLine("Press any key to stop the service and exit the application");
                Console.ReadKey();
            }
        }

        private static void Configuration(IAppBuilder builder)
        {
            HttpConfiguration configuration = new HttpConfiguration();
            HttpServer server = new HttpServer(configuration);
            configuration.Routes.MapHttpRoute(
                name: "api",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });
            builder.UseWebApi(server);
        }

        public class Customer
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }

        public class WebCustomersController : ApiController
        {
            CustomersContext context = new CustomersContext();
            [Queryable(PageSize = 10, MaxExpansionDepth = 2)]
            public IHttpActionResult Get()
            {
                return Ok(context.Customers);
            }

            public async Task<IHttpActionResult> Post([FromBody] Customer entity)
            {
                if (entity == null)
                {
                    return BadRequest(ModelState);
                }
                context.Customers.Add(entity);
                await context.SaveChangesAsync();
                return CreatedAtRoute("api", new { controller = "ApiCustomers" }, entity);
            }

            public async Task<IHttpActionResult> Put(int id, [FromBody] Customer entity)
            {
                if (entity == null)
                {
                    return BadRequest(ModelState);
                }
                else if (id != entity.Id)
                {
                    return BadRequest("The key from the url must match the key of the entity in the body");
                }
                var originalCustomer = await context.Customers.FindAsync(id);
                if (originalCustomer == null)
                {
                    return NotFound();
                }
                else
                {
                    context.Entry(originalCustomer).CurrentValues.SetValues(entity);
                    await context.SaveChangesAsync();
                }
                return Content(HttpStatusCode.OK, entity);
            }

            public async Task<IHttpActionResult> Delete(int id)
            {
                Customer entity = await context.Customers.FindAsync(id);
                if (entity == null)
                {
                    return NotFound();
                }
                else
                {
                    context.Customers.Remove(entity);
                    await context.SaveChangesAsync();
                    return StatusCode(HttpStatusCode.NoContent);
                }
            }
        }

        public class CustomersContext : DbContext
        {
            static CustomersContext()
            {
                Database.SetInitializer<CustomersContext>(new CustomersContextInitializer());
            }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }

            private class CustomersContextInitializer : DropCreateDatabaseAlways<CustomersContext>
            {
                protected override void Seed(CustomersContext context)
                {
                    Fixture fixture = new Fixture();
                    IEnumerable<Customer> customers = fixture.CreateMany<Customer>(20).ToList();
                    context.Customers.AddRange(customers);
                }
            }

            public DbSet<Customer> Customers { get; set; }
        }
    }
}

这是给客户的:

namespace client_batch
{
    class Program
    {
        static void Main(string[] args)
        {
            start();
        }

        private async static void start()
        {
            Fixture fixture = new Fixture();
            HttpClient client = new HttpClient();

            dynamic listOfCustomers = JToken.Parse(await client.GetStringAsync("http://localhost:12345/api/WebCustomers"));
            dynamic firstCustomer = listOfCustomers[0];
            firstCustomer.Name = "Peter";
            dynamic secondCustomer = listOfCustomers[1];
            JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();

            //Create a request to query for customers
            HttpRequestMessage queryCustomers = new HttpRequestMessage(HttpMethod.Get, "http://localhost:12345/api/WebCustomers");
            //Create a message to add a customer
            HttpRequestMessage addCustomer = new HttpRequestMessage(HttpMethod.Post, "http://localhost:12345/api/WebCustomers");
            addCustomer.Content = new ObjectContent<Customer>(fixture.Create<Customer>(), formatter);
            //Create a message to update a customer
            HttpRequestMessage updateCustomer = new HttpRequestMessage(HttpMethod.Put, string.Format("http://localhost:12345/api/WebCustomers/{0}", firstCustomer.Id));
            updateCustomer.Content = new ObjectContent<dynamic>(firstCustomer, formatter);
            //Create a message to remove a customer.
            HttpRequestMessage removeCustomer = new HttpRequestMessage(HttpMethod.Delete, string.Format("http://localhost:12345/api/WebCustomers/{0}", secondCustomer.Id));

            //Create the different parts of the multipart content
            HttpMessageContent queryContent = new HttpMessageContent(queryCustomers);
            HttpMessageContent addCustomerContent = new HttpMessageContent(addCustomer);
            HttpMessageContent updateCustomerContent = new HttpMessageContent(updateCustomer);
            HttpMessageContent removeCustomerContent = new HttpMessageContent(removeCustomer);

            //Create the multipart/mixed message content
            MultipartContent content = new MultipartContent("mixed", "batch_" + Guid.NewGuid().ToString());
            content.Add(queryContent);
            content.Add(addCustomerContent);
            content.Add(updateCustomerContent);
            content.Add(removeCustomerContent);

            //Create the request to the batch service
            HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, "http://localhost:12345/api/batch");
            //Associate the content with the message
            batchRequest.Content = content;
        }

        public class Customer
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    }
}

我是 c# 的新手,所以任何指点都将不胜感激!

最佳答案

当您在异步方法的代码中使用 await 关键字时,您真正告诉程序的是“听着,你继续工作,到时给我回电话你完成了(当然,这不是那么简单,编译器为我们做了很多我们看不到的开销,你可以阅读它 here )”。

所以你的代码中实际发生的是

dynamic listOfCustomers = JToken.Parse(await client.GetStringAsync("http://localhost:12345/api/WebCustomers"));

将控制权交还给调用者,在本例中调用者是称为 start() 的方法,由于它是 Main 方法,因此无法等待。 start 拿回了控制权并且没有等待,所以下一行代码继续执行,这导致您的程序结束。

你需要做的是在开始时等待(),这样当控制权被收回时它就不会结束:

class Program
{
  static void Main(string[] args)
  {
    start().Wait();
  }

  private async static void start()
  {
    Fixture fixture = new Fixture();
    HttpClient client = new HttpClient();

    dynamic listOfCustomers = JToken.Parse(await client.GetStringAsync("http://localhost:12345/api/WebCustomers").ConfigureAwait(false));
     // Rest Of Code..
  }

关于c# - await client.GetStringAsync 无一异常(exception)退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23224449/

相关文章:

c# - DBCC SHRINKFILE 的进展

c# - Html.BeginForm 内的 Ajax.BeginForm

c# - 在 WPF 应用程序中加密凭据

php - json 日期对象到 php 日期

.net - System.Uri实现ISerializable,但给出错误?

.net - 如何对刚刚消失的.NET应用程序进行故障排除?

c# - 无法声明接口(interface) "async Task<myObject> MyMethod(Object myObj); "

asp.net - DotNet 核心设置失败

c# - 系统.线程.任务.并行

c# - 对 DropDownList 进行排序?