3

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

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

例如:

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

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

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

示例 2:备份程序。

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

4

4 回答 4

3

听起来您正在尝试异步调用事件调用列表中的委托。

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

.NET Framework 为我们提供了在我们的类中异步引发事件(和其他项)的概念。这意味着我们可以以不让该事件的订阅者(通常是用户界面)阻止引发事件的方法中的处理的方式引发事件。好处是它不会对我们的业务层方法的性能产生负面影响。

于 2009-05-21T00:36:30.447 回答
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 类本身。

于 2009-05-21T01:01:42.690 回答
1

让第一个事件除了启动线程之外什么都不做,那么有什么其他事件侦听器就无关紧要了。

于 2009-05-21T00:32:32.077 回答
1

对于您的备份程序案例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");

这个链接告诉你异步编码的不同技术

于 2009-05-21T08:13:47.960 回答