Проблема в том, что 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 : Если это кажется слишком хакерским, то это потому, что это так.«Правильный» подход заключается в использовании пользовательского SynchronizingObject
.К сожалению, похоже, что нет встроенного, но есть статья , описывающая, как создать очередь делегатов , которая реализует ISynchronizeInvoke
.
Чистый эффект этого подходато же самое: в конечном итоге вы что-то сидите в главном потоке, ожидаете вызовов, которые нужно запросить, а затем выполняете их.Только на этот раз вы можете закодировать все эти возможности, в то же время делая программу немного более зависимой от использования системных ресурсов.