2012-03-20 53 views
0

新手到C#這裏,第一次處理事件處理程序。我正在編寫的程序的一個步驟涉及每次在某個位置創建文件時更改剪貼板。以下是我想出迄今:FileSystemEventHandler後更改剪貼板

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Threading; 
using System.Windows.Forms; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     [STAThread] 
     public static void Main() 
     { 
      FileSystemWatcher watcher = new FileSystemWatcher(); 
      watcher.Path = @"C:\Input\"; 
      watcher.Filter = "*.csv"; 
      watcher.Created += new FileSystemEventHandler(ProcessFile); 
      watcher.EnableRaisingEvents = true; 
      Console.ReadLine(); 
     } 
     public static void ProcessFile(object source, FileSystemEventArgs e) 
     { 
      try 
      { 
       Clipboard.SetText("text"); 
      } 
      catch (Exception exc) 
      { 
       Console.WriteLine(exc); 
       Console.ReadKey(); 
      } 
     } 
    } 
} 

拋出異常當前線程不是STA模式,需要在Main方法被標記,但我相信,我這樣做。我如何在這裏更改剪貼板?

回答

1

問題是FileSystemWatcher將在單獨的線程上觸發事件。您需要執行某些操作,以便剪貼板操作在與您的Main方法相同的線程中進行。

方法#1:使用Application.Run,即使您不使用WinForms。它所做的是在主線程上旋轉一個循環,等待事件。事情是這樣的:

static Form InvokerForm; 

public static void Main() 
{ 
    InvokerForm = new Form(); 
    var dummy = InvokerForm.Handle; // form handle creation is lazy; force it to happen 

    var watcher = new FileSystemWatcher(); 
    watcher.SynchronizingObject = InvokerForm; 
    watcher.Path = @"C:\Input\"; 
    watcher.Filter = "*.csv"; 
    watcher.Created += new FileSystemEventHandler(ProcessFile); 
    watcher.EnableRaisingEvents = true; 

    Application.Run(); 
} 

這告訴觀察者打電話給你創建(不可見)的形式Invoke,通過你的處理程序作爲一個參數。這基本上排隊它以後調用。與此同時,Application.Run坐落在主線程上,旋轉循環等待這樣的事件發生。當它注意到時,它會繼續並在正確的線程上調用ProcessFile

方法#2:如果這看起來太hacky,那是因爲它是。 「正確的」方法是使用定製的SynchronizingObject。不幸的是,似乎並沒有內置的,但有一篇文章describing how to create a delegate queue實現了ISynchronizeInvoke

這種方法的最終效果是一樣的:您最終會在您的主線程中放置一些東西,等待調用請求,然後執行它們。只有這一次,你才能編寫所有的內部代碼,同時使程序在系統資源使用上稍微精簡。