代码之家  ›  专栏  ›  技术社区  ›  Chris Thompson

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

  •  2
  • Chris Thompson  · 技术社区  · 15 年前

    我有一个关于.NET事件的问题。我必须为一些情况编写代码,在这些情况下,我有一个后台任务正在运行,并且我想通知一个主线程或控制器类发生了一些事情,例如任务已完成,或者文件复制已完成,但是我不希望后台任务等待主线程的委托处理事件。

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

    例如:

    一个类被编写成按顺序处理多个进程,一个接一个。每个进程都需要在后台线程上运行。当工作完成时,一个事件激发并通知控制器它已经完成(比如使用onCompleted()方法)

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

    在这种情况下,后台任务如何通知控制器类在不将事件引发方法保留在堆栈上的情况下完成了工作?

    例2: 备份程序。

    运行后台线程将每个文件复制到目标。背景需要 通知 用户界面是上次复制的文件,但不需要等待用户界面更新。相反,它只是想说,“顺便说一句,这里有一些信息。现在,让我回去工作。”事件监听器不应该阻止事件引发器的处理。

    4 回复  |  直到 15 年前
        1
  •  2
  •   Mark Brackett Achilles Ram Nakirekanti    15 年前

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

    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
  •  3
  •   Andrew Hare    15 年前

    听起来好像您正试图异步调用事件调用列表中的委托。

    我建议你读 .NET Asynchronous Events To Send Process Status To User Interface :

    .NET框架为我们提供了 提出事件(及其他)的概念 项)在我们的类中异步。 这意味着我们可以提高活动 以这样一种方式 订阅该事件(通常 用户界面)。 在引发的方法中处理 事件。好处是它 不会对 我们业务层的性能 方法。

        3
  •  1
  •   Luke Schafer    15 年前

    让第一个事件什么也不做,只是启动线程,那么其他事件监听器有什么就无关紧要了。

        4
  •  0
  •   Rashmi Pandit    15 年前

    备份程序的案例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编码技术