2015-01-06 2 views
1

Windows 응용 프로그램을 만들려고하고 있으며 작업을 완료하는 데 몇 분이 걸리는 기능이 있습니다. 시작 버튼이 있고 중지 버튼을 추가하려고 할 때마다 기능 처리를 중지하기 위해 중지 버튼을 추가하고 싶습니다.시간이 많이 걸리는 기능을 위해 스레드를 중지하는 방법

아래 코드를 시도했지만 Thread1이 "현재 컨텍스트에서 "으로 표시되어 있기 때문에 btnStop에서 Thread1을 중단하는 방법을 모르겠습니다.

제발 나를 권해주십시오./이것을 어떻게 좋은 방향으로 이끌어 낼 수 있는지 설명해주십시오. 미리 감사드립니다.

namespace SampleStartStop 
{  
    public partial class Form1 : Form 
    {   
     public Form1() 
     { 
      InitializeComponent();    
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      Thread Thread1 = new Thread(SlowFunction);    
      Thread1.Start();       
     } 

     private void btnStop_Click(object sender, EventArgs e) 
     { 
      Thread1.Abort(); 
      MessageBox.Show("Processing canceled"); 
     } 
     public void SlowFunction() 
     { 
      var end = DateTime.Now + TimeSpan.FromSeconds(10); 
      while (DateTime.Now < end) 
      { } 
      MessageBox.Show("Process finished"); 
     } 

    } 
} 

업데이트 : 안녕 KCdod, 난 단지 내가 " 'System.NullReferenceException' 이 SampleStartStop.exe에서 발생 유형의 처리되지 않은 예외"GET 글로벌 변수로 스레드를 선언 당신의 도움에 대한 감사합니다.

안녕하세요, Alexei 님, 수정 해 주셔서 감사합니다. 취소 토큰에 대한 공유에 감사하는 zerkms 및 Alexei. 링크 된 예에서 다음을 공유했습니다. 아래 코드를 작성할 수있었습니다. 그것은 작동하는 것처럼 보이지만 약간의 변화가 필요하거나 괜찮 으면 전문가의 승인을 받고 싶습니다.

중지 버튼을 누르면 잘 처리되지 않지만 다시 시작 버튼을 클릭하면 아무 일도 일어나지 않고 응용 프로그램을 닫고 다시 열어야 작동합니다. 다시 시작 버튼이 정상입니까?

"청취자"내부에는 의심의 여지가 있습니다. MSDN 예제에서는 "// 필요한 경우 정리 수행"을 했으므로 어떤 종류의 정리 작업을 수행하고 있습니까? ?

public partial class Form1 : Form 
{  
    public Form1() 
    { 
     InitializeComponent();    
    } 
    // Create the token source. 
    CancellationTokenSource cts = new CancellationTokenSource(); 

    private void btnStart_Click(object sender, EventArgs e) 
    { 
     // Pass the token to the cancelable operation. 
     ThreadPool.QueueUserWorkItem(new WaitCallback(SlowFunction), cts.Token);      
    } 

    private void btnStop_Click(object sender, EventArgs e) 
    { 
     // Request cancellation. 
     cts.Cancel(); 
     // Cancellation should have happened, so call Dispose. 
     cts.Dispose(); 

     MessageBox.Show("Processing canceled"); 
    } 
    public void SlowFunction(object obj) 
    { 
     CancellationToken token = (CancellationToken)obj; 

     var end = DateTime.Now + TimeSpan.FromSeconds(10); 
     while (DateTime.Now < end) 
     { 
      // Thread 2: The listener 
      if (token.IsCancellationRequested) 
      { 
       // Perform cleanup if necessary. 
       //... 
       // Terminate the operation.     
       break; 
      } 
     } 
     if (!token.IsCancellationRequested) 
     { 
      MessageBox.Show("Processing finished"); 
     } 
    } 

} 

업데이트 : 당신의 교정을위한 감사 알렉세이, 나는 당신의 제안 코드를 수정 한이 시간이 좋은 작동합니다. 코드는 다음과 같습니다. 실제 코드에서는 함수가 문자열 인자를 필요로하기 때문에 "WaitCallback (SlowFunction)"부분에서 호출하는 방법과 코드에서 함수를 정의하는 방법을 알지 못합니다. 이 "공개 무효 SlowFunction (개체 obj) {...}"같이 정의하고 내 실제 함수에서이 "공개 void SlowFunction (문자열 str)"같습니다. 나는이 문제에 대해 새로운 질문을 할 필요가 있다고 생각한다.

namespace SampleStartStop 
{  
    public partial class Form1 : Form 
    {  
     // Create the token source. 
     CancellationTokenSource cts = new CancellationTokenSource(); 

     public Form1() 
     { 
      InitializeComponent();    
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      if (cts != null) 
      { 
       cts.Cancel(); 
      }   
      // Pass the token to the cancelable operation. 
      cts = new CancellationTokenSource(); 
      ThreadPool.QueueUserWorkItem(new WaitCallback(SlowFunction), cts.Token);       
     } 

     private void btnStop_Click(object sender, EventArgs e) 
     { 
      if (cts != null) 
      { 
       cts.Cancel(); 
       cts = null; 
       MessageBox.Show("Processing canceled"); 
      } 
     } 
     public void SlowFunction(object obj) 
     { 
      CancellationToken token = (CancellationToken)obj; 

      var end = DateTime.Now + TimeSpan.FromSeconds(5); 
      while (DateTime.Now < end) 
      { 
       if (token.IsCancellationRequested) 
       {     
        break; 
       } 
      } 
      if (!token.IsCancellationRequested) 
      { 
       MessageBox.Show("Processing finished"); 
      } 
     } 

    } 
} 
+1

취소 토큰 --- http://msdn.microsoft.com/en-us/library/dd997289(v=vs.110).aspx – zerkms

답변

1

스레드를 Thread Thread1;으로 전역 변수로 선언 할 수 있습니다. 현재 코드에서 Thread1 범위가 btnStart_Click() 이벤트 기능으로 제한됩니다.

namespace SampleStartStop 
{  
    public partial class Form1 : Form 
    { 
     Thread Thread1=null; 
     public Form1() 
     { 
      InitializeComponent();    
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      Thread1 = new Thread(SlowFunction);    
      Thread1.Start();       
     } 

     private void btnStop_Click(object sender, EventArgs e) 
     { 
      Thread1.Abort(); 
      MessageBox.Show("Processing canceled"); 
     } 
     public void SlowFunction() 
     { 
      var end = DateTime.Now + TimeSpan.FromSeconds(10); 
      while (DateTime.Now < end) 
      { } 
      MessageBox.Show("Process finished"); 
     } 

    } 
} 

Additional - 스레드 중단은 좋지 않지만 사용할 수 있습니다.

4

협력하지 않는 스레드를 종료하는 좋은 방법은 없습니다. 사실 Thread.Abort은 그렇게 할 것이지만 잠재적으로 비 처리 된 객체를 버리고 동기화 프리미티브를 포기함으로써 잠재적으로 프로그램을 불안정하게 만들 수 있습니다.

바로 문제를 해결하십시오. Thread1을 로컬 변수 대신 클래스 수준 멤버로 이동하십시오.당신은 이미 설정/해제되어 있는지 확인해야합니다 :

public partial class Form1 : Form { 
    ... 

    Thread thread1 = null;    

    private void btnStart_Click(object sender, EventArgs e) 
    { 
    if (thread1 != null) 
    { 
     thread1.Abort(); 
    } 
    thread1 = new Thread(SlowFunction);    
    Thread1.Start();       
    } 

    private void btnStop_Click(object sender, EventArgs e) 
    { 
    if (thread1 != null) 
    { 
     thread1.Abort(); 
     thread1 = null; 
     MessageBox.Show("Processing canceled"); 
    } 
} 

그것은 될 것입니다 훨씬 더 당신이 종료에 협력 "느린 기능"할 수 있다면 - 주기적으로 일부 값을 확인하여, 즉. .Net 방식으로 확인하려면 Cancellation tokens을 확인하십시오.

+0

안녕 Alexei, 많은 도움을 주셔서 감사합니다. 원래 게시물에서 내 업데이트를 보시기 바랍니다. – Sarmeu

+0

@Sarmeu 당신은 내 샘플에서 객체의 레크리에이션을 복사하지 않으므로 취소 토큰은 스레드의 모든 시작 시마다 새로 시작하는 대신 영원히 취소 된 상태로 유지됩니다. –

+0

안녕 알렉세이, 물건의 레크 리 에이션을 무엇을 의미합니까? 내가 게시하고 작업 한 샘플을 테스트했습니다. 취소 작업에 협조 할 수있는 기능을 만드는 것이 더 좋을 것이라고 말했을 때, 나는 당신이 공유 한 링크에서와 마찬가지로해야한다고 생각했습니다. 그렇다면 샘플과 제 2 코드의 혼합이 무엇을 제안합니까? 다시 감사합니다 – Sarmeu

관련 문제