2014-10-02 5 views
1

최근 새 응용 프로그램 작업을 시작합니다.이 응용 프로그램은 매우 대역폭이 제한된 환경에서 사용됩니다. 내 디자이너는 데이터를로드하는 데 걸리는 시간에 대해 우려하고 있습니다.저장 프로 시저 호출 취소

리스트 뷰 선적을 클릭하면 사이드 패널을 표시, 선적 가득 다음과 같이

현재 우리는 시스템을 가지고있다. 사이드 패널에 "자세히"버튼이 있습니다.이 버튼을 클릭하면 저장 프로 시저가 호출되어 선택된 발송물 세부 정보가로드됩니다.

이전 응용 프로그램에서는 스레드가 발생하지 않았으므로로드 시간이 너무 적어 문제가 발생하지 않았습니다 (내부 네트워크에 있음). 그러나 새로운 제한 사항으로 인해 프로 시저 호출을 호출하고 로딩 애니메이션을 표시하지만 디자이너는 로딩을 취소 할 수있는 기능을 추가하려고합니다.

단추가 정적 리포지토리 (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); 
     } 
    } 

어떻게 내가 메인 스레드 A로부터이 방법을 취소 할 수있는 기능을 추가하는 방법에 대한 갈 수 다음과 같이

리포지토리 LoadDetails

은?

+0

각 LoadDetails에 대해 새 스레드를 만들고 있습니까? thread.abort()를 사용할 수 없습니까? 또는 저장 프로 시저 호출을 취소 하시겠습니까? – artm

+0

대역폭이 병목 현상이있는 경우 가장 많은 리소스를 소비하는 작업은 DataAdapter.Fill (모든 데이터를 net로 읽어야 함)입니다. 비동기로 만들고 취소하도록하십시오. http://stackoverflow.com/questions/2108917/sqldataadapter-fill-asynchronous-approach –

+0

SqlCommand.Cancel도 있습니다. – artm

답변

2

.NET 코드에서 백그라운드 작업을 강제로 취소 할 수있는 안전하고 신뢰할 수있는 방법은 없습니다. 단, 별도의 프로세스에서 작업을 실행하고 범용 솔루션이 아닌 프로세스를 종료해야합니다. 특히 그 작업이 현재 원시 코드를 실행하고 있다면.

당신이 할 수있는 최선의 옵션

은 다음과 같습니다

  • 가 덩어리로 엄청난 양의 데이터를 분할;
  • 는 사용자 누를 경우 현재 레코드와 위치를 떠나처럼, "취소"버튼 (또는 완료 뭔가 비슷한,
  • 현재로드 작업의 결과 잊어 (thisthis 참조) 코드에서 우아한 취소 패턴을 따르도록 다음에).

나는 SqlCommand.Cancel에 의존하지 않을 것입니다. Thread.Abort도 옵션이 아닙니다.

+0

'Thread.Abort'와'SqlCommand.Cancel'가 왜 나쁜 선택인지 자세히 설명해 주시겠습니까? –

+0

'Thread.Abort'에 관해서 : http://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread-abort'SqlCommand.Cancel'에 대해서 : 문서에서 말했듯이'Cancel' 그냥 * 시도합니다. 취소하려면 *. 이 시도는 성공할 수 있습니다. (그리고 객관적 이유가있을 수도 있습니다.)또한, '취소'가 귀하의 요구 사항에 맞는 시간에 종료된다는 보장은 없습니다. – Dennis