在cmd应用程序中的任务内链接ASYNC任务会导致崩溃而没有异常

时间:2019-04-30 18:20:29

标签: c# asynchronous

编辑: 这是我的主要方法

static void Main(string[] args)
{
    LogNewOrders();
    DataTable initialData = ControllerSqlAgent.SelectQuery(Resources.Controller, Resources.qryGetInitalData);
    Console.WriteLine($"|There are {initialData.Rows.Count} orders to check|");
    Task.WhenAll(UpdateItemCountsField(initialData));
}

我有一个名为UpdateItemCountsField(datatable)的方法

此方法的目的是同时获得两者:

  • 已取消的物品总数
  • 总发货量

    private static async Task UpdateItemCountsField(DataTable initialData)
    {
        try
        {
            foreach (DataRow row in initialData.Rows)
            {
                string narvarId = row["NarvarID"].ToString();
                int orderedItemCount = (int)row["ItemsOrdered"];
                int totalShippedItems = (int)row["ItemsShipped"]; ;
                int totalCancelledItems = (int)row["ItemsCancelled"];
                string locateConstraint = GetLocateInConstraint(row["OrderNumber"].ToString(), row["CompanyNumber"].ToString());
                Task<int> totalShippedItemsTask = CheckShipmentCountsAsync(locateConstraint, row["OrderNumber"].ToString(), row["CompanyNumber"].ToString(), totalShippedItems, narvarId);
                Task<int> totalCancelledItemsTask = CheckCancellationCountsAsync(locateConstraint, row["OrderNumber"].ToString(), row["CompanyNumber"].ToString(), totalCancelledItems, narvarId); ;
                int[] result = await Task.WhenAll(totalShippedItemsTask, totalCancelledItemsTask);
                //totalShippedItems = CheckShipmentCounts(locateConstraint, row["OrderNumber"].ToString(), row["CompanyNumber"].ToString(), totalShippedItems, narvarId);
                //totalCancelledItems = CheckCancellationCounts(locateConstraint, row["OrderNumber"].ToString(), row["CompanyNumber"].ToString(), totalCancelledItems, narvarId);
                Console.WriteLine($"|ID:{narvarId}|Ordered: {orderedItemCount}|Shipped: {result[0]}|Cancelled: {result[1]}|");
                Console.WriteLine("|___________________________________________|");
            }
        }
        catch
        {
            throw;
        }
    }
    

我有两个从异步方法中获得的Task对象:

Task<int> totalShippedItemsTask = CheckShipmentCountsAsync(params);
Task<int> totalCancelledItemsTask = CheckCancellationCountsAsync(params);

然后我得到这样的结果(这是程序崩溃的地方)

int[] result = await Task.WhenAll(totalShippedItemsTask,totalCancelledItemsTask);
CheckShipmentCoutnsAsync(params)CheckCancellationCountsAsync(params)中的

是另外两个Task<int>对象。这是因为我必须从中提取两个数据源

   private static async Task<int> CheckShipmentCountsAsync(string locateConstraint, string orderNumber, string companyNumber, int currentShippedItemCount, string narvarId)
    {
        Task<int> wmsShippedCountTask = WmsSqlAgent.GetCountOfShippedItemsAsync(orderNumber, companyNumber);
        Task<int> locateShippedCountTask = LocateSqlAgent.GetCountOfShippedItemsAsync(locateConstraint);
        int[] result = await Task.WhenAll(wmsShippedCountTask, locateShippedCountTask);
        int newShippedItemCount = result.Sum();
        if (newShippedItemCount > currentShippedItemCount)
            ControllerSqlAgent.UpdateShippedItemCount(narvarId, newShippedItemCount);
        return newShippedItemCount;
    }

方法CheckCancelCountsAsync(PARAMS)与上述方法相同,但要取消。

我的程序运行时,它命中任务,然后崩溃而没有任何异常,并且永远不会到达下一个数据行以执行异步方法。我在这里想念一块吗?为什么我的应用程序毫无例外地崩溃。我之所以认为它崩溃是因为它从未进入Console.Writeline();在我从Task.WhenAll

获得结果数组之后

这是检索实际计数的数据源方法

internal static async Task<int> GetCountOfCancelledItemsAsync(string orderNumber, string companyNumber)
{
    int itemCount = 0;
    await Task.Run(() =>
    {
        try
        {
            using (var connection = new SqlConnection(Resources.WMS))
            {
                connection.Open();

                using (var command = new SqlCommand(Resources.qryWmsGetCancelledItemCount, connection))
                {
                    command.Parameters.AddWithValue("@orderNumber", orderNumber);
                    command.Parameters.AddWithValue("@companyNumber", companyNumber);
                    itemCount = int.Parse(command.ExecuteScalar().ToString());
                }

                connection.Close();
            }
        }
        catch (SqlException E)
        {
            string message = E.Message;
            throw;
        }
        return itemCount;
    });
    return itemCount;

单步执行代码时,我可以看到我进入nt[] result = await Task.WhenAll(totalShippedItemsTask, totalCancelledItemsTask);时程序崩溃,但仍然没有例外。

1 个答案:

答案 0 :(得分:1)

您尚未在主要方法中等待Task.WhenAll(UpdateItemCountsField(initialData))的结果。这意味着程序将退出而无需等待该代码完成执行。

将方法更改为此:

static async Task Main(string[] args)
{
    LogNewOrders();
    DataTable initialData = ControllerSqlAgent.SelectQuery(Resources.Controller, Resources.qryGetInitalData);
    Console.WriteLine($"|There are {initialData.Rows.Count} orders to check|");
    await UpdateItemCountsField(initialData);
}

由于UpdateItemCountsField返回一个Task,因此Task.WhenAll包装它是多余的,所以我从答案中的代码中删除了它。

请注意,您must be using C# 7.1或更高版本才能使用异步main方法。

确保在返回Task的任何方法中,您await的结果。