2009-11-20 15 views
0

可能重複:
Locking main() thread保活一個線程在C#應用程序

下面你會發現我的代碼,主要調用兩個線程,一個啓動的事件處理程序返回的值它們被更改後的註冊表項。另一個設置計時器,每隔幾分鐘將更改寫入一個XML文件。基本上,我希望一遍又一遍地運行寫操作,但希望啓動事件處理程序只運行一次,但仍然可以接受事件。有沒有辦法做到這一點?任何等待處理程序仍然允許代碼運行等?請注意,這是一個後臺應用程序,沒有控制檯,因爲我不希望任何用戶與系統進行交互(我通常知道服務是要走的路,但是當我在運行服務時詢問類似問題時,我被告知要做應用程序和應用程序對於我如何運行/使用它更有意義。)

public class 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(); 
    } 
} 

public class runner 
{ 
    RegistryValueChange valuechange; 
    List<regkey> RegKeys = new List<regkey>(); 
    static object locker = new object(); 

    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); 

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

    void valuechange_RegistryValueChanged(object sender, RegistryValueChangedEventArgs e) 
    { 
    } 

    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) 
    { 
     lock (locker) 
     { 
      file write = new file(); 
      write.write(RegKeys); 
     } 
    } 
} 
+0

您是否已經問過並接受同一個問題的答案? http://stackoverflow.com/questions/1722932/locking-main-thread – 2009-11-20 09:29:49

+0

LOL!我正在忙着寫一個漂亮的答案......主要是說以前的答案是一樣的...... – 2009-11-20 09:31:42

回答

1
  • 你不需要創建一個線程來啓動計時器就可以了。您可以在主線程中啓動計時器。它的函數將在線程池中的一個線程上運行。

  • 我不明白你爲什麼需要爲start()函數創建一個線程。它需要至少部分運行,然後您的計時器首次運行。所以,你可以在主線程中執行RegKeys = load.read(RegKeys);(也可能是start的其他代碼)。如果您堅持要在單獨的線程中運行它,請確保RegKeys已初始化。它可以通過例如在初始化RegKeys並在定時器回調中等待此ManualResetEvent後設置ManualResetEvent

  • 您應該在進程退出時停止計時器。

  • 您需要等待啓動線程停止使用Thread.Join方法或通過等待某個WaitHandle(例如,ManualResetEvent)在完成時在線程中設置。

0

您的代碼有幾個問題。首先你的Start()方法應該做一個循環。如果沒有,它會執行一次,然後退出,從而完成線程。

您的主應用程序只是啓動線程,然後退出,因此當代碼到達應用程序中的右括號時,它就會結束。在退出Main方法之前,您必須等待線程結束。

此外,整個過程可能會非常棘手。首先,定時器在主線程中通過中斷和窗口消息到窗口消息循環執行,因爲這是一個控制檯應用程序,所以在定時器事件提出時,您的應用程序肯定會完成。 Here您可以看到如何在控制檯應用程序中使用計時器(請注意,它不需要在單獨的線程中創建)。請注意,委託從線程池線程調用,從而避免在runner「two」中創建。

最後,考慮到你必須保持你的主應用程序運行,直到發生什麼事情使它退出。也就是說,你必須在你的Main上設置一個循環來允許你的應用程序等待發生的事情,無論是用戶輸入,網絡消息還是其他什麼......基本上你會等待「退出」命令。