【问题标题】:Why does the application sillently die even without an exception?为什么即使没有异常,应用程序也会默默地死掉?
【发布时间】:2018-03-30 13:53:09
【问题描述】:

.NET Core 2

当客户端尝试向服务器发送get 请求时,它会立即死亡。如果我使用Postman,那么它工作正常,但我需要通过 C# 来完成。这是我的一段代码,用于从服务器获取文件:

var client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(timeSpanFromMinutes);

try
{
    // At this code row the application shutdown without any exception. 
    // Even doesn't work the 'catch' block of try\catch...
    HttpResponseMessage response = await client.GetAsync(url + "/Home/Download/" + args[1], 
        HttpCompletionOption.ResponseContentRead);
    // I will not be here    
    Console.WriteLine("Response status code: {0}", response.StatusCode);
    if (response.StatusCode == HttpStatusCode.OK)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            await response.Content.CopyToAsync(ms);
            Console.WriteLine("Data successfully recieved from server. Data length: {0}",
                ms.Length);

            string resultFileName = Path.Combine(resultFolder, new Guid().ToString()
                                                     + resultFileExtension);
            using (FileStream fs = new FileStream(resultFileName, FileMode.Create))
            {
                fs.Read(ms.GetBuffer(), 0, (int) ms.Length);
            }

            Console.WriteLine("The result was saved in the '{0}' file.", resultFileName);
        }
    }
}
catch (Exception ex)
{   // I will not be here
    Console.WriteLine("Exception: {0}", ex.Message);
}

服务器已启动并可访问。所有变量都被初始化并包含有效值。 post 请求没有问题。我有get 请求的问题。我评论了问题代码行。

这种行为的原因是什么?

UPD

这是我客户端的完整代码(问题在于“get”命令):

using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
           var task = Task.Run(()=>{
                Work(args);
           });
           task.Wait();
        }

        static async Task Work(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("Application invalid parameters.");
                WriteHelp();
                return;
            }

            string xmlFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                "Client.settings.xml");

            XElement xml = XElement.Load(xmlFileName);

            string url = xml.Element("url").Value?.Trim()?.TrimEnd('/');
            string resultFolder = Environment.ExpandEnvironmentVariables(xml.Element("resultsFolder").Value);

            if (!Directory.Exists(resultFolder))
            {
                Directory.CreateDirectory(resultFolder);
            }

            string resultFileExtension = Environment.ExpandEnvironmentVariables(xml.Element("resultFileExtension").Value);
            int timeSpanFromMinutes = Int32.Parse(xml.Element("TimeSpanFromMinutes").Value);

            switch (args[0])
            {
                // Send data to server
                case "post":
                {
                    string fileName = Environment.ExpandEnvironmentVariables(args[1]);

                    if (!File.Exists(fileName))
                    {
                        Console.WriteLine("File '{0}' not found.", fileName);
                        return;
                    }
                    else
                    {
                        var client = new HttpClient();
                        client.Timeout = TimeSpan.FromMinutes(timeSpanFromMinutes);

                        try
                        {
                            using (FileStream fs = new FileStream(fileName, FileMode.Open))
                            {
                                HttpResponseMessage response = await client.PostAsync(url + "/Home/Upload", 
                                    new StreamContent(fs));

                                Console.WriteLine("Response status code: {0}", response.StatusCode);
                                if (response.StatusCode == HttpStatusCode.OK)
                                {
                                    // The task ID. It is to be used for get the data handling result from server later.
                                    string id = await response.Content.ReadAsStringAsync();
                                    Console.WriteLine("Task ID: {0}", id);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Exception: {0}", ex.Message);
                        }
                    }

                    break;
                }
                // get the result of data handling from server
                case "get":
                {
                    Guid guid = Guid.Empty;

                    if (!Guid.TryParse(args[1], out guid))
                    {
                        Console.WriteLine("Invalid identifier (GUID): '{0}'", args[1]);
                        return;
                    }

                    var client = new HttpClient();
                    client.Timeout = TimeSpan.FromMinutes(timeSpanFromMinutes);

                        try
                        {
                            // TODO: the problem is here
                            var response = await client.GetAsync(url + "/Home/Download/" + args[1], 
                                HttpCompletionOption.ResponseContentRead);

                            Console.WriteLine("Response status code: {0}", response.StatusCode);
                            if (response.StatusCode == HttpStatusCode.OK)
                            {
                                using (MemoryStream ms = new MemoryStream())
                                {
                                    await response.Content.CopyToAsync(ms);
                                    Console.WriteLine("Data successfully recieved from server. Data length: {0}",
                                        ms.Length);

                                    string resultFileName = Path.Combine(resultFolder, new Guid().ToString()
                                                                             + resultFileExtension);
                                    using (FileStream fs = new FileStream(resultFileName, FileMode.Create))
                                    {
                                        fs.Read(ms.GetBuffer(), 0, (int) ms.Length);
                                    }

                                    Console.WriteLine("The result was saved in the '{0}' file.", resultFileName);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Exception: {0}", ex.Message);
                        }

                    break;
                }
                default:
                {
                    Console.WriteLine("Unknown command: {0}", args[0]);
                    WriteHelp();
                    return;
                }
            } 
        }

        private static void WriteHelp()
        {
            string text =
@"
Client.dll
(c) Andrey Bushman, 2018

This client allows to send data to server and get the results of their handling.

The application using format:

    dotnet Client.dll <command> <parameter>

## COMMAND

    post - send file to server. The request contains status code and GUID for getting the data handling result later.

    get - get data handling result by GUID. If result doesn't exist still then recuest code is 'File not found'. 

## PARAMETER

    It is the file full name for the 'post' command or the GUID for the 'get' command.

## EXAMPLES

Upload the file to server:

    dotnet Client.dll post /home/andrey/tmp/data.foo

Download the data handling result from server by GUID:

    dotnet Client.dll get 3d600895-f11c-4fa0-865e-411d52daf469";

            Console.WriteLine(text);
        }
    }
}

完整的代码来源是 GitHub 上的here

【问题讨论】:

  • 你需要展示调用这个函数的代码。
  • 好的,我添加了 UPD 部分。
  • 您要下载的文件有多大?
  • 服务器不包含必要的文件。但我看到服务器甚至没有收到请求。在这种情况下,服务器将发送“找不到文件”响应。
  • 客户端在尝试发送get 请求时立即死亡。

标签: c# asp.net .net asp.net-core async-await


【解决方案1】:

注意编译器警告:

 var task = Task.Run(()=>{
     Work(args);
 });
 task.Wait();

它应该告诉你Work(args) 没有在这里等待。这意味着它抛出的任何异常都不会被观察到。

由于我们在控制台应用程序中,Task.Run() 没有真正的用途。
请改用以下内容:

static void Main(string[] args)
{
    try
    {
        var task = Work(args);
        task.Wait();
    }
    catch (Exception ex)
    {
       // log or put a breakpoint here        
    }
}

【讨论】:

  • 如果这是 C# 7.1,我们也可以做static async Task Main 并等待任务。
  • 是的,但这会改善什么吗?
  • 当然——你应该避免打电话给.Wait()。您应该改为等待任务。这就是使应用程序可以具有异步 main 方法的全部意义。
  • 避免在控制台应用程序中使用.Wait()。它认为这并不重要。使用任何你想要的东西,但要在它周围加上 try/catch。
  • 另见thisthis:“只是语法糖”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多