取消对存储过程的调用

时间:2014-10-02 11:02:12

标签: c# multithreading stored-procedures

我们最近开始研究新的应用程序,该应用程序将在带宽有限的环境中使用。因此,我的设计师担心加载数据所花费的时间。

目前我们有一个系统如下:

列出了货件的Listview,点击货件会显示一个侧面板。 侧面板上有一个按钮"详细信息"单击此按钮将进行存储过程调用以加载所选货件的详细信息。

现在在我们之前的应用程序中,这没有线程化,加载时间非常小,不会引起任何问题(在内部网络上)。然而,由于新的限制,我们现在将调用过程线程化并显示加载动画,但是我的设计师想要添加取消加载的功能。

这就是我被困的地方,因为按钮在我的静态存储库(LoadDetails)上调用单个方法我看不到取消此加载的方法。除此之外,用户可以选择货件点击详细信息,然后选择第二个,第三个货件点击所有这些的详细信息,假脱机多个线程加载数据。

Repository LoadDetails如下:

private static bool LoadDetails(int shipmentId)
    {
        DataConnection dbCon = null;
        try
        {
            dbCon = ApplicationRoleService.EnableAppRole();
            if (dbCon.SqlConn == null)
            {
                return false;
            }

            SqlCommand cmd = new SqlCommand("LBN.sel_shipments_details");
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = dbCon.SqlConn;

            SqlParameter paramShipmentId = new SqlParameter();
            paramShipmentId.ParameterName = "shipment_id";
            paramShipmentId.Direction = ParameterDirection.Input;
            paramShipmentId.Value = shipmentId;
            cmd.Parameters.Add(paramShipmentId);

            SqlParameter paramReturn = new SqlParameter();
            paramReturn.ParameterName = "@return_value";
            paramReturn.Direction = ParameterDirection.ReturnValue;
            cmd.Parameters.Add(paramReturn);

            SqlDataAdapter adp = new SqlDataAdapter(cmd);
            DataSet ds = new DataSet();
            adp.Fill(ds);

            if ((int)paramReturn.Value < 0)
            {
                //TODO: Log Error here.
                log.Error("Get Shipment Details Failed.");
            }

            foreach (DataRow row in ds.Tables[0].Rows)
            {
                App.Current.Dispatcher.Invoke((System.Action)delegate
                {
                    Shipment s = GetShipment(shipmentId);
                    s.ShipmentDetails(
                          row["bankContact"] as string,
                          row["bankContactTel"] as string,
                          (row["containerCount"] == DBNull.Value) ? 0 : (int)row["containerCount"],
                          (row["sentToSiteComp"] == DBNull.Value) ? 0 : (int)row["sentToSiteComp"], 
                          (row["arrivedAtSiteComp"] == DBNull.Value) ? 0 : (int)row["arrivedAtSiteComp"],                                                          
                          (row["sentToPortComp"] == DBNull.Value) ? 0 : (int)row["sentToPortComp"],
                          (row["depostRecComp"] == DBNull.Value) ? 0 : (int)row["depostRecComp"]
                        );
                });
            }
            IoC.Get<IEventAggregator>().PublishOnUIThread(new ShipmentDetailsLoaded());
            return true;
        }
        catch (Exception ex)
        {
            log.Error("Unable to get ShipmentsList.", ex);
            return false;
        }
        finally
        {
            ApplicationRoleService.CloseConnection(dbCon);
        }
    }

我怎样才能添加从主线程中取消此方法的功能?

1 个答案:

答案 0 :(得分:2)

除了在单独的进程中运行操作并终止进程(这不是通用解决方案)之外,没有可靠且安全的方法来强制取消.NET代码中的任何后台操作。特别是,如果该操作目前正在运行本机代码。

您可以在这里做的最佳选择是:

  • 将大量数据分成块;
  • 在您的代码中遵循优雅的取消模式(请参阅thisthis
  • 忘记当前加载操作的结果,如果用户按下“取消”按钮(或做了类似的事情,比如将当前记录和定位留在下一个)。

我不依赖SqlCommand.CancelThread.Abort也不是一种选择。