2010-01-13 5 views
2

.net WinForms 응용 프로그램이 있습니다. 나는 User Action을 기반으로 인스턴스화 된 UserControl을 가지고있다. 인스턴스화시, ajaxy 회전 애니메이션을 표시하면서 BackgroundWorker를 사용하여 백그라운드 스레드에서 시간이 많이 걸리는 작업을 수행한다. 사용자는 언제든지 클릭 한 다음 배경 컨트롤을 다시 클릭하여 배경 스레드를 다시 시작할 수 있습니다.WinForms 앱에서 백그라운드 작업을 종료하는 데 허용되는 패턴은 무엇입니까

사용자가 클릭 할 때 UserControl 및 보유하고있는 모든 리소스 (백그라운드 스레드 포함)를 삭제하고 싶습니다. 이 일을하는 가장 좋은 방법은 무엇입니까?

+0

폼이 포커스를 잃었을 때 처분하고 싶다고 말하고 있습니까? – ChaosPandion

+0

@Chaos, 폼이 포커스를 잃지 않을 때가 아닙니다. 이 앱에는 Outlook 스타일의 인터페이스가 있습니다. 사이드 바의 다른 항목으로 전환 할 때, 그 시점부터 처리하고 싶습니다. – AngryHacker

답변

1

BackgroundWorker에서 CancelAsync 메서드를 호출하고 종료 될 때까지 기다립니다. 취소 플래그가 있는지 자주 확인하도록 작업자 코드를 구성하십시오.

잠시 동안 스레드가 계속 실행 되어도 부작용이없고 사용자 정의 컨트롤이나 스레드가 보유한 리소스를 참조하지 않을 경우 스레드를 요청한 후 사용자 정의 컨트롤을 삭제할 수 있습니다. 끝내다.

편집 : 데모 코드

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class FrmMain : Form 
    { 
     public FrmMain() 
     { 
      InitializeComponent(); 
     } 

     private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      MessageBox.Show("BG Done"); 
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      bg.WorkerSupportsCancellation = true; 
      bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted); 
      bg.DoWork += new DoWorkEventHandler(bg_DoWork); 
      bg.RunWorkerAsync(); 
     } 

     void bg_DoWork(object sender, DoWorkEventArgs e) 
     { 
      int i=0; 

      while (!bg.CancellationPending) 
      { 
       lblStatus.BeginInvoke((MethodInvoker) delegate { lblStatus.Text = i + " sec."; }); 
       System.Threading.Thread.Sleep(1000); 
       i++; 
      } 

      lblStatus.BeginInvoke((MethodInvoker)delegate { lblStatus.Text = "CANCEL"; }); 
     } 

     private void btnStop_Click(object sender, EventArgs e) 
     { 
      bg.CancelAsync(); 
      while (bg.IsBusy) // For real code limit max wait time in while loop 
      { 
       System.Threading.Thread.Sleep(50); 
       Application.DoEvents(); 
      } 
      this.Close(); 
     } 
    } 
} 


namespace WindowsFormsApplication1 
{ 
    partial class FrmMain 
    { 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.bg = new System.ComponentModel.BackgroundWorker(); 
      this.btnStart = new System.Windows.Forms.Button(); 
      this.btnStop = new System.Windows.Forms.Button(); 
      this.lblStatus = new System.Windows.Forms.Label(); 
      this.SuspendLayout(); 
      // 
      // bg 
      // 
      this.bg.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bg_RunWorkerCompleted); 
      // 
      // btnStart 
      // 
      this.btnStart.Location = new System.Drawing.Point(39, 13); 
      this.btnStart.Name = "btnStart"; 
      this.btnStart.Size = new System.Drawing.Size(75, 23); 
      this.btnStart.TabIndex = 0; 
      this.btnStart.Text = "Start"; 
      this.btnStart.UseVisualStyleBackColor = true; 
      this.btnStart.Click += new System.EventHandler(this.btnStart_Click); 
      // 
      // btnStop 
      // 
      this.btnStop.Location = new System.Drawing.Point(39, 42); 
      this.btnStop.Name = "btnStop"; 
      this.btnStop.Size = new System.Drawing.Size(75, 23); 
      this.btnStop.TabIndex = 1; 
      this.btnStop.Text = "Stop"; 
      this.btnStop.UseVisualStyleBackColor = true; 
      this.btnStop.Click += new System.EventHandler(this.btnStop_Click); 
      // 
      // lblStatus 
      // 
      this.lblStatus.AutoSize = true; 
      this.lblStatus.Location = new System.Drawing.Point(39, 72); 
      this.lblStatus.Name = "lblStatus"; 
      this.lblStatus.Size = new System.Drawing.Size(73, 13); 
      this.lblStatus.TabIndex = 2; 
      this.lblStatus.Text = "(Not Running)"; 
      // 
      // FrmMain 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(423, 136); 
      this.Controls.Add(this.lblStatus); 
      this.Controls.Add(this.btnStop); 
      this.Controls.Add(this.btnStart); 
      this.Name = "FrmMain"; 
      this.Text = "Main"; 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     private System.ComponentModel.BackgroundWorker bg; 
     private System.Windows.Forms.Button btnStart; 
     private System.Windows.Forms.Button btnStop; 
     private System.Windows.Forms.Label lblStatus; 
    } 
} 
+0

BGW에 RunWorkerCompleted 이벤트 처리기가있을 때 교착 상태가 될 때까지 기다리지 마십시오. –

+0

사실이 아니지만 기다리는 동안 Application.DoEvents()를 호출해야합니다. (VS 2010/NET 4) –

1

당신은 Progress Changed Event에 후크 할 수 있습니다. 일을 잃지 않고 안전하게 멈출 수있을 때마다 작업자에게이 이벤트를 호출하게하십시오. 이제이 값을 ProgressChangedEventArgs으로 설정하여 작업의 현재 상태를 저장할 수 있습니다. 작업을 중단하지 않고 중단 한 부분부터 다시 시작할 수 있습니다.

+0

을 보여주는 추가 된 코드 UserControl이 결과를 반환 할 때까지 기본적으로 차단중인 먼 서비스를 치기 때문에 실제로 그렇게 할 수 없습니다. – AngryHacker

관련 문제