Winform 진도 바 탄창 과 작업 제어 실현

최근 에 Winform 프로젝트 에 기능 을 추가 하려 면 진 도 를 표시 할 수 있 는 팝 업 창 이 필요 하고 작업 을 중단 할 수 있 도록 요구 하기 때문에 하 나 를 만 들 었 습 니 다.여기 서 기록 정 리 를 하 겠 습 니 다.오래된 Winform 기술 을 사 용 했 지만 그 원 리 는 모두 통 했다.
탄창 프론트
우선 Winform 컨트롤 가운데 에 있 는 작은 기술 을 제공 합 니 다.
컨트롤 을 TableLayoutPanel 용기 에 넣 고 컨트롤 의 Anchor 속성 을 None 으로 설정 하면 컨트롤 이 용기 가운데 에 있 습 니 다.

용기 의 Anchor 속성 을 Top,Left,Right,이렇게 하면 용기 가 창 좌우 로 늘 어 날 수 있 습 니 다.

최종 창 창 창 창 은 다음 과 같 습 니 다:

사용 하 다 CSkin 인터페이스 라 이브 러 리(v 16.1.14.3),창 계승 Skin_DevExpress,진도 바 는 SkinProgressBar 를 사용 하고 단 추 는 SkinButton 을 사용 합 니 다.주로 원 각 효 과 를 사 용 했 습 니 다.

2.탄창 배경
먼저 두 개의 이 벤트 를 추가 하여 외부 구독 을 제공 합 니 다.각각 창 이 불 러 올 때 발생 하 는 실행 이벤트 와 중단 단 추 를 누 른 후에 발생 하 는 종료 작업 이벤트 입 니 다.

/// <summary>
///       
/// </summary>
public event Action OperateAction;

/// <summary>
///       
/// </summary>
public event Action AbortAction;

/// <summary>
///         
/// </summary>
private void btn_Abort_Click(object sender, EventArgs e)
{
  AbortAction?.Invoke();
  DialogResult = DialogResult.Abort;
  //Close(); //       ;
}

/// <summary>
///       
/// </summary>
private void FormProgressDialog_Load(object sender, EventArgs e)
{
  Task.Factory.StartNew(() =>
  {
    OperateAction?.Invoke();
    DialogResult = DialogResult.OK;
  });
}
중지 단 추 를 누 른 뒤 팝 업 창 결 과 를 Abort 로 설정 하면 자동 으로 팝 업 창 이 닫 힙 니 다.업무 수행 이 정상적으로 끝 났 고,팝 업 창 결 과 는 OK 였 다.
외부 에서 텍스트 정보 와 진도 항목 의 진 도 를 설정 하 는 방법 은 다음 과 같다.

/// <summary>
///       (  null     )
/// </summary>
/// <param name="rtfTitleContent">          </param>
/// <param name="totalMessage">    </param>
/// <param name="currentMessage">    </param>
public void SetInfo(string rtfTitleContent = null, string totalMessage = null, string currentMessage = null)
{
  if (rtfTitleContent != null) rtb_Title.Rtf = rtfTitleContent;
  if (totalMessage != null) lbl_Total.Text = totalMessage;
  if (currentMessage != null) lbl_Current.Text = currentMessage;
}

/// <summary>
///     
/// </summary>
/// <param name="currentValue">    </param>
/// <param name="totalValue">   </param>
public void SetProsess(double currentValue, double totalValue)
{
  try
  {
    progressBar.Value = (int)(currentValue / totalValue * 100);
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
  }
}
나머지 는 부 텍스트 상자 인 RichTextBox 를 설정 하 는 두 가지 방법 입 니 다.컬러 내용 을 설정 하고 RichTextBox 커서 를 숨 기 는 방법 을 포함 합 니 다.글 끝 에 코드 주 소 를 드 립 니 다.여기 서 더 이상 언급 하지 않 습 니 다.
3.사용 방법
먼저 눈 에 띄 는 것 은 두 구성원 변수 입 니 다.하 나 는 작업 취소 에 사용 되 는 CancellationTokenSource 대상 이 고 다른 하 나 는 스 레 드 동기 화 에 사용 되 는 AutoResetEvent 대상 입 니 다.그 다음 에 메 인 테스트 방법(하나의 단 추 를 누 르 면 이벤트 방법)의 정보 설정 입 니 다.

그리고 설정 CancellationTokenSource 대상 의 Token 은 작업 을 취소 할 때 호출 하 는 의뢰 방법 을 등록 합 니 다.동기 신호 결 과 를 기다 리 고 이번 실행 결 과 를 판단 합 니 다.

다음 에 팝 업 창 에 있 는 두 이 벤트 를 구독 하고 작업 이벤트 에서 작업 을 시작 하여 Token 을 전달 합 니 다.이벤트 중지 중 작업 정지:

주의해 야 할 것 은 작업 을 중지 한 후에 작업 내부 가 스스로 멈 추 지 않 습 니 다.Token 의 IsCancellationRequestion 필드 를 판단 하여 해당 하 는 작업 을 결정 해 야 합 니 다.예 를 들 어 순환 을 끝 내 는 것 입 니 다.그 다음 에 기 존 에 등 록 된 취 소 된 위탁 방법 에서 대기 가 이 루어 졌 기 때문에 저 희 는 업무 방법(Business Method)을 수행 하고 관련 상태 값 을 설정 한 후에 임무 취소 여 부 를 판단 해 야 합 니 다.취소 하면 등 록 된 취 소 를 설명 하 는 위탁 방법 에서 이미 기다 리 고 있 기 때문에 Set()를 호출 하여 통과 시 켜 야 합 니 다.
foreach 순환 이 시 작 될 때 취소 여 부 를 판단 하지 않 았 느 냐 고 물 을 수도 있 습 니 다.여 기 는 어떻게 또 판단 합 니까?예 를 들 어 한 번 의 순환 에서 시작 이 취소 되 었 는 지 에 대한 판단(IsCancellationrequest 는 false)을 실 행 했 고 시간 이 걸 리 는 업무 방법 을 실 행 했 기 때 문 입 니 다.이때 사용자 가 중지 단 추 를 누 르 면 IsCancellationrequest 는 true 로 설정 되 어 있 기 때문에 업무 방법 을 실행 한 후에 최신 상 태 를 판단 할 수 있 습 니 다.그리고...순환 은 다음 라운드 가 시 작 될 때 끝 납 니 다.
또한 이 프로젝트 를 실제로 사용 하 는 것 은.NET 4.0 프레임 워 크 이기 때문에 Task 의 일부 방법 은 없습니다.여러분 이 새로운 프레임 워 크 를 사용 하면 새로운 방법 을 사용 할 수 있 습 니 다.또는 사용 Microsoft.Bcl.Async 가방 을 사용 합 니 다. TaskEx。
프로 세 스 를 계속 하고 다음 에 모드 상자 로 창 을 팝 업 하고 결 과 를 가 져 옵 니 다.업무 처리 방법 에서 시간 소모 작업 을 모 의 하고 성공 여 부 를 되 돌려 줍 니 다.

마지막 으로 전체 코드 를 드 립 니 다:

#region          

private CancellationTokenSource _Cts; //      ;
private AutoResetEvent _AutoResetEvent = new AutoResetEvent(false);//    false,  WaitOne      ;

/// <summary>
///         
/// </summary>
private void BtnProgressDialog_Click(object sender, EventArgs e)
{
  _AutoResetEvent.Reset();
  string businessName = "  1";

  FormProgressDialog progressWindow = new FormProgressDialog()
  {
    Text = "      ",
  };

  progressWindow.SetColorfulTitle("  1 ", Color.DarkOrange, true);
  progressWindow.SetColorfulTitle("     ......", Color.Black);
  progressWindow.SetInfo(null, "", "");

  List<string> orders = new List<string>(){"  1", "  2", "  3", "  4", "  5" }; //    ;
  List<string> leftList = orders.Select(x => x).ToList(); //  (   )  ;
  int successCount = 0; //    ;

  _Cts = new CancellationTokenSource();

  //          CancellationToken       ;
  _Cts.Token.Register(async () =>
  {
    ShowInfo("    ");
    
    await Task.Run(() =>
    {
      _AutoResetEvent.WaitOne(1000 * 5); //              ;

      if (successCount < orders.Count)
      {
        ShowInfo($"{businessName}   {orders.Count - successCount}       ,           。");

        foreach (var leftName in leftList)
        {
          ShowInfo($"【{businessName}】 【{leftName}】    ,    :【    】。");
        }
      }
    });
    
  });

  progressWindow.OperateAction += () =>
  {
    Task task = new Task(() =>
    {
      foreach (var order in orders)
      {
        //       ;
        if (_Cts.Token.IsCancellationRequested)
        {
          break;
        }

        progressWindow.TryBeginInvoke(new Action(() =>
        {
          progressWindow.SetInfo(null, $" {orders.Count} ,   {successCount} ", $"      :{order}");
        }));

        if (BusinessMethod(order, businessName))
        {
          successCount++;
          leftList.RemoveAll(x => x == order);

          if (_Cts.Token.IsCancellationRequested)
          {
            _AutoResetEvent.Set(); //   Register       ;
          }
        }

        progressWindow.TryBeginInvoke(new Action(() =>
        {
          progressWindow.SetProsess(orders.IndexOf(order) + 1, orders.Count);
        }));
      }
    }, _Cts.Token);

    task.Start();
    task.Wait();
  };

  progressWindow.AbortAction += () =>
  {
    _Cts.Cancel();
  };

  var result = progressWindow.ShowDialog();
  int leftCount = orders.Count - successCount;
  if (result == DialogResult.OK || leftCount <= 0)
  {
    ShowInfo($"{businessName}     。");
  }
  else if (result == DialogResult.Abort)
  {
    //   _Cts.Token.Register      ,        ;
    //ShowInfo($"{businessName}   {leftCount}       ,           。");
  }
}

/// <summary>
///       
/// </summary>
private bool BusinessMethod(string order, string businessName)
{
  string errStr = $"【{businessName}】  {order}     ,    :";

  //  
  Thread.Sleep(1000 * 2);

  try
  {
    //    ;

    ShowInfo($"【{businessName}】  {order}       。");
    return true;
  }
  catch (Exception ex)
  {
    ShowInfo($"{errStr}{ex.Message}");
  }

  return false;
}

#endregion
4.효과 전시 와 코드 주소
정상 실행(움 직 이 는 그림):

실행 중지(움 직 이 는 그림):

코드 주소:https://gitee.com/dlgcy/Practice/tree/master/WinFormPractice
전재 하 다
이상 은 Winform 이 진도 바 팝 업 창 과 작업 통 제 를 실현 하 는 상세 한 내용 입 니 다.Winform 진도 바 팝 업 창 과 작업 통제 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기