如何在不等待事件侦听器运行的情况下触发事件?

时间:2009-05-21 00:28:34

标签: c# events messages

我对.NET(C#)中的事件有疑问。我不得不为我运行后台任务的几种情况编写代码,我想通知主线程或控制器类发生了什么事情,例如任务完成,或者完成复制文件,但我不知道我希望后台任务等待主线程的委托处理事件。

我想做一些像消息传递这样的事情:发送消息,但是谁在乎他们用它做什么。

例如:

编写一个类来按顺序处理多个进程,一个接一个。每个进程都需要在后台线程上运行。当工作完成时,一个事件触发并告诉控制器它已完成(假设使用OnCompleted()方法)

问题在于,如果控制器的事件处理程序用于启动后续进程,则先前进程的OnComplete方法将保留在调用堆栈上(永远不会执行),直到所有进程都完成为止。

在那种情况下,后台任务如何通知控制器类工作完成而不保留事件提升方法?

示例2:备份程序。

后台线程运行以将每个文件复制到目标。后台需要通知 UI最后复制的文件,但不需要等待UI更新。相反,它只是想说,“顺便说一下,这里有一些信息。现在,让我重新开始工作。”事件监听器不应阻止事件提升者的处理。

4 个答案:

答案 0 :(得分:3)

听起来你试图异步调用事件的调用列表中的委托。

我建议您阅读.NET Asynchronous Events To Send Process Status To User Interface

  

.NET Framework为我们提供了   提高事件的概念(和其他   我们的类中的项目是异步的。   这意味着我们可以举起活动   以这样的方式,没有   订阅者(通常是   用户界面)举起来   在提出的方法中处理   事件。好处是它   不会对此产生负面影响   我们业务层的表现   方法

答案 1 :(得分:2)

您可以在引发事件时进行异步调用(如上所述),或者只是在后台线程上引发事件本身:

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

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

如果异步引发,多个侦听器将同时处理您的事件。至少,这需要一个线程安全的EventArg类。如果您希望它们也与您的班级互动,那么您应该非常仔细地记录或使其也是线程安全的。

在后台线程上引发事件对您的类方法有相同的警告,但您不必担心EventArgs类本身。

答案 2 :(得分:1)

让第一个事件除了启动线程之外什么都不做,那么其他事件监听器是什么并不重要。

答案 3 :(得分:0)

对于你的备案程序2。代码示例将异步触发文件副本,一旦完成复制,它将调用回调方法。在回调中,如果您不想等待UI更新,那么您将不得不异步调用UI更新代码

您可以使用异步委托

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

这个link告诉你asyn编码的不同技术