Изменение буфера обмена после FileSystemEventHandler - PullRequest
0 голосов
/ 20 марта 2012

Новичок в c # здесь, впервые имея дело с обработчиками событий.один шаг программы, которую я пишу, включает изменение буфера обмена каждый раз, когда файл создается в определенном месте.Вот что я придумал:

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 Ответ

1 голос
/ 20 марта 2012

Проблема в том, что 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.

Чистый эффект этого подходато же самое: в конечном итоге вы что-то сидите в главном потоке, ожидаете вызовов, которые нужно запросить, а затем выполняете их.Только на этот раз вы можете закодировать все эти возможности, в то же время делая программу немного более зависимой от использования системных ресурсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...