Как я могу запустить событие, не дожидаясь запуска слушателей событий? - PullRequest
2 голосов
/ 21 мая 2009

У меня есть вопрос о событиях в .NET (C #). Мне пришлось написать код для нескольких ситуаций, в которых у меня запущена фоновая задача, и я хочу уведомить основной поток или класс контроллера о том, что что-то произошло, например, о завершении задачи или о завершении копирования файла, но я не не хочу, чтобы фоновая задача ожидала, пока представитель основного потока обработает событие.

Я хочу сделать что-то вроде передачи сообщений: отправьте сообщение, но кого волнует, что они с ним делают.

Например:

Класс написан для последовательной обработки нескольких процессов, один за другим. Каждый процесс должен выполняться в фоновом потоке. Когда работа завершена, событие запускается и сообщает контроллеру, что оно выполнено (скажем, с помощью метода OnCompleted ())

Проблема заключается в том, что если для запуска последующего процесса используется обработчик событий контроллера, то метод OnComplete предыдущих процессов остается в стеке вызовов (никогда не завершается) до тех пор, пока не завершатся все процессы.

В этой ситуации, как фоновая задача может уведомить класс контроллера о том, что работа выполнена, не сохраняя метод вызова событий в стеке?

Пример 2: Программа резервного копирования.

Фоновый поток запускается для копирования каждого файла в место назначения. Фон должен уведомлять интерфейс последнего файла, который был скопирован, но ему не нужно ждать обновления интерфейса. Вместо этого он просто хочет сказать: «Кстати, вот некоторая информация. Теперь позвольте мне вернуться к работе». Слушатель событий не должен блокировать обработку обработчика событий.

Ответы [ 4 ]

3 голосов
/ 21 мая 2009

Звучит так, будто вы пытаетесь вызвать делегатов в списке вызовов события асинхронно.

Я бы посоветовал вам прочитать .NET асинхронные события для отправки статуса процесса в пользовательский интерфейс :

.NET Framework предлагает нам концепция возбуждения событий (и др. предметы) в наших классах асинхронно. Это означает, что мы можем поднять событие таким образом, чтобы не иметь подписчик на это событие (как правило, пользовательский интерфейс) задержать обработка в методе, который поднял событие. Преимущество в том, что это не оказывает негативного влияния на производительность нашего бизнес уровня способ.

2 голосов
/ 21 мая 2009

Вы можете сделать асинхронный вызов при вызове события (как уже упоминалось) или просто вызвать само событие в фоновом потоке:

void OnUpdated(EventArgs e) {
   EventHandler h = this.Updated;
   if (h != null) h(e);
}

void DoStuff() {
   BigMethod();
   ThreadPool.QueueUserWorkItem(OnUpdated, EventArgs.Empty);
   BigMethod2();
}

Если вы вызываете асинхронно, несколько слушателей будут обрабатывать ваше событие одновременно. По крайней мере, для этого требуется потокобезопасный класс EventArg. Если вы ожидаете, что они также будут взаимодействовать с вашим классом, то вам следует очень тщательно документировать или сделать его поточно-ориентированным.

Повышение события в фоновом потоке несет те же предостережения для ваших методов класса, но вам не нужно беспокоиться о самом классе EventArgs.

1 голос
/ 21 мая 2009

Пусть первое событие ничего не делает, кроме как запускает поток, тогда не имеет значения, какие есть другие слушатели событий.

0 голосов
/ 21 мая 2009

Для вашего случая 2 программы резервного копирования. Пример кода запускает копию файла асинхронно, и, как только копия будет сделана, она вызывает метод обратного вызова. В обратном вызове, если вы не хотите ждать обновления пользовательского интерфейса, вам придется вызывать код обновления пользовательского интерфейса асинхронно

Вы можете использовать асинхронные делегаты

public class AsyncFileCopier
    {
        public delegate void FileCopyDelegate(string sourceFile, string destFile);

        public static void AsynFileCopy(string sourceFile, string destFile)
        {
            FileCopyDelegate del = new FileCopyDelegate(FileCopy);
            IAsyncResult result = del.BeginInvoke(sourceFile, destFile, CallBackAfterFileCopied, null);
        }

        public static void FileCopy(string sourceFile, string destFile)
        { 
            // Code to copy the file
        }

        public static void CallBackAfterFileCopied(IAsyncResult result)
        {
            // Notify UI by calling an async del (probably using fire & forget approach or another callback if desired)
        }
    }

Вы можете назвать это как:

AsyncFileCopier.AsynFileCopy("abc.txt", "xyz.txt");

Эта ссылка рассказывает вам различные методы асинхронного кодирования

...