2009-11-12 5 views
1

여기에 전문 용어가 확실하지는 않지만 여기서는 기본적으로 응용 프로그램의 main() 스레드가 시작되어 두 개의 스레드를 호출합니다. 하나는 특정 레지스트리 키를 기다리는 이벤트 처리기를 설정합니다. 다른 하나는 5 분마다 xml 파일에 대한 변경 사항을 기록하기 위해 타이머를 시작하고 계속 실행됩니다. 내가 가진 문제는 일단 호출 된 두 메소드가 초기화되면 프로그램은 main으로 돌아가서 프로그램을 종료한다는 것입니다. 내 관련 코드 섹션 아래에서 찾을 수 있습니다, 그래서 어떤 도움을 주시면 감사하겠습니다 :메인() 스레드를 잠급니다.

static void Main(string[] args) 
    { 
     runner one = new runner(); 
     runner two = new runner(); 

     Thread thread1 = new Thread(new ThreadStart(one.TimerMeth)); 
     Thread thread2 = new Thread(new ThreadStart(two.start)); 

     thread1.Start(); 
     thread2.Start(); 

     thread1.Join(); 
     thread2.Join(); 
    } 

public void TimerMeth() 
    { 
     System.Timers.Timer timer = new System.Timers.Timer(); 

     timer.Elapsed += new ElapsedEventHandler(OnElapsedTime); 

     timer.Interval = 300000; 

     timer.Enabled = true; 
    } 

    private void OnElapsedTime(object source, ElapsedEventArgs e) 
    { 
     file write = new file(); 
     write.write(RegKeys); 
    } 

public void start() 
     { 
      if (File.Exists("C:\\test.xml")) 
      { 
       file load = new file(); 
       RegKeys = load.read(RegKeys); 
      } 

      string hiveid = "HKEY_USERS"; 
      WindowsIdentity identity = WindowsIdentity.GetCurrent(); 
      string id = identity.User.ToString(); 

      string key1 = id + "\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows Messaging Subsystem\\\\Profiles\\\\Outlook\\\\0a0d020000000000c000000000000046"; 
      List<string> value1 = new List<String> { "01020402", "test" }; 

      valuechange = new RegistryValueChange(hiveid, key1, value1); 
      valuechange.RegistryValueChanged += new EventHandler<RegistryValueChangedEventArgs>(valuechange_RegistryValueChanged); 

      try 
      { 
       valuechange.Start(); 

      } 
      catch 
      { 
       StreamWriter ut; 
       ut = File.AppendText("C:\\test.txt"); 
       ut.WriteLine("error occured in starting management"); 
       ut.Close(); 
      } 

      file test = new file(); 
      test.checkfile("C:\\test.xml"); 

     } 

void valuechange_RegistryValueChanged(object sender, RegistryValueChangedEventArgs e) 
     { 
// deals with the returned values 
} 

기본적으로 모든 코드는 내가 윈도우 폼 응용 프로그램에서 테스트를 봤는데 잘 작동하지만 지금은 독립에 실행해야 응용 프로그램을 백그라운드에서 인터페이스없이 사용하고 XML 파일 및 변경 이벤트를 계속 작성하려면 계속 살아 있어야합니다.

+0

'main' 루틴 내에서'Console.ReadLine();'과 같은 것을 추가하려고 했습니까 (간섭하지 않고 종료하지 않으려 고합니다)? 나는 그것을 시도하지 않았지만 그것이 효과가 있는지보기 위해 단지 몇 분이 걸릴 것입니다. –

답변

1

메소드가 한 번 실행되면 스레드가 종료됩니다. 그들을 계속 운영 할 아무 것도 없습니다.

이 시도 : 다른 포스터가 언급 한

thread1.IsBackground = true; 
thread2.IsBackground = true; 

public void start() 
{ 
while(true) 
{ 
    // ... do stuff 
    Thread.Sleep(1000*60*5) // sleep for 5 minutes 
} 
} 

public void TimerMeth() 
{ 
    while(true) 
    { 
     file write = new file(); 
     write.write(RegKeys); 

     Thread.Sleep(30000); 
    } 
} 

으로, 당신은 또한 다음의 주요 방법은 종료하지 않도록해야합니다. 응용 프로그램을 Windows 서비스로 만드는 것이이 문제를 해결할 수있는 좋은 방법 인 것 같습니다.

스레드에 ThreadInterruptedExceptionThreadAbortException을 처리 할 수도 있습니다.

그리고 실로 스레딩에 신경써 쓰고 싶다면 Joe Albahari가이 Free C# Threading E-Book을 확인하십시오.

+0

건배는 도움이 된 작은 전자 서적을 통해 코드가 떨어지는 것을 막을 수있었습니다. – manemawanna

2

windows service에 이것을 시험해보십시오.

thread에는 Windows 서비스에서 로그온 한 사용자를 찾는 두 가지 제안이 포함되어 있지만 제대로 작동하는지 확실하지 않습니다.

+0

이미 로그온 한 사용자 (로컬 시스템, 로컬 서비스 또는 네트워크 서비스에서 반환 된 SID가 원하는대로 실행되지 않음)로 실행해야하는 경우와는 별개로 작동하는 작업을 수행하고있었습니다. 이미이를 해결하는 방법에 대한 질문을 게시했으며 Windows 서비스 대신 .exe를 만들 것을 제안했습니다. – manemawanna

2

메서드는 실행이 Join() 메서드에서 기본 스레드로 다시 진행되어 종료되기 때문에 종료됩니다.

TimerMeth()start() 메서드에 루프를 배치하거나 더 적절하게 응용 프로그램을 Windows 서비스로 다시 디자인하십시오 (zac의 설명처럼).

0

ThreadStart 함수가 반환 될 때 Thread이 끝나기 때문에 Join() 이후에 주 스레드가 계속 될 수 있습니다. 발사 타이머를 설정하기 만하면이 메서드는 매우 빠르게 반환됩니다. 응용 프로그램이 종료되지 않게하려면 일종의 잠금 장치를 제공해야합니다.

또한, 시도하고있는 것을하기 위해 스레드를 전혀 사용하지 않아도되는 것처럼 보입니다. 대신 Timer을 사용하고 Main()이 종료되지 않도록 자물쇠를 제공하십시오.

2

몇 가지 문제가 있습니다.

첫 번째 스레드는 단순히 다른 스레드를 시작하는 타이머를 만드는 것입니다. 이 스레드는 매우 빨리 종료되므로 Join에 전화하는 것은 의미가 없습니다. 이 스레드가 수행해야하는 것은 실제로 대기 및 확인 작업을 수행하는 것입니다.당신은 쉽게 다음과 같은 코드를 적용 할 수 있습니다 : 그들은 여기에 사용되지 않기 때문에

public void TimerMeth() 
{ 
    System.Timers.Timer timer = new System.Timers.Timer(); 

    timer.Elapsed += new ElapsedEventHandler(OnElapsedTime); 

    timer.Interval = 300000; 

    timer.Enabled = true; 

    try 
    { 
     while(true) 
     { 
      OnElapsedTime(null, null); // you should change the signature 

      Thread.Sleep(30000); 
     } 
    } 
    catch(ThreadAbortException) 
    { 
     OnElapsedTime(null, null); 

     throw; 
    } 
} 

은 분명히 당신은 , 매개 변수를 제거하기 위해 OnElapsedTime의 서명을 변경해야합니다.

파일 핸들링 방식이 다소 엉망이라는 생각이 들지만 그 코드 이 정확히을 이해할 수 없다는 점을 감안할 때 나는 코멘트를하지 않을 것입니다. 파일의 목적은 정확히 무엇입니까? RegKeys은 어디에 정의되어 있습니까?

0

모든 기능이 완료되는 것처럼 보입니다. 즉, 그들은 모두 "바닥에서 떨어집니다". 모든 기능이 끝나면 남은 일과 앱이 종료됩니다. 메인에서 어떤 종류의 루프를 돌리고 싶다.

또한 타이머를 살펴볼 필요가 있습니다. 나는 그것이 현재 쓰레기 수집되고 있다고 생각합니다. 함수의 범위 내에서 함수를 만들지 만 해당 함수가 남아 있으므로 더 이상 타이머에 대한 참조가 없으므로 함수가 수집됩니다. 타이머가 루트 여야합니다.

관련 문제