如何在不等待事件监听器运行的情况下触发事件?
我对.NET(C#)中的事件有疑问。 我必须编写代码,用于运行后台任务的几种情况,并且我想通知主线程或控制器类已发生某些事情,例如任务已完成,或已完成复制文件,但我不知道t希望后台任务等待主线程的委托处理事件。
我想做一些像消息传递这样的事情:发送消息,但谁在乎他们用它做什么。
例如:
编写一个类来依次处理多个进程,一个接一个。 每个进程都需要在后台线程上运行。 当工作完成时,事件触发并告诉控制器它已完成(假设使用OnCompleted()方法)
问题是如果控制器的事件处理程序用于启动后续进程,则先前进程的OnComplete方法将保留在调用堆栈上(永远不会完成执行),直到所有进程完成为止。
在那种情况下,后台任务如何通知控制器类工作完成而不在堆栈上保留事件提升方法?
示例2:备份程序。
后台线程运行以将每个文件复制到目标。 后台需要通知 UI最后复制的文件,但不需要等待UI更新。 相反,它只是想说,“顺便说一句,这里有一些信息。现在,让我重新开始工作。” 事件监听器不应阻止事件提升者的处理。
在引发事件时(如上所述),您可以执行异步调用,或者只在后台线程上引发事件本身:
void OnUpdated(EventArgs e) { EventHandler h = this.Updated; if (h != null) h(e); } void DoStuff() { BigMethod(); ThreadPool.QueueUserWorkItem(OnUpdated, EventArgs.Empty); BigMethod2(); }
如果异步引发,多个侦听器将同时处理您的事件。 至少,这需要一个线程安全的EventArg类。 如果您希望它们也与您的class级进行交互,那么您应该非常仔细地记录或者使其成为线程安全的。
在后台线程上引发事件对您的类方法有相同的警告,但您不必担心EventArgs类本身。
听起来你正试图异步调用事件的调用列表中的委托。
我建议您阅读.NET异步事件以将进程状态发送到用户界面 :
.NET Framework为我们提供了异步提升类中事件(和其他项)的概念。 这意味着我们可以通过这样一种方式引发事件,即不让该事件的订阅者(通常是用户界面)在引发事件的方法中保持处理。 好处是它不会对我们的业务层方法的性能产生负面影响。
让第一个事件除了启动线程之外什么都不做,那么其他事件监听器是什么并不重要。
对于你的案例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");
此链接告诉您asyn编码的不同技术
- 代表和Lambdas和LINQ,哦,我的!
- 如何解决Dynamics CRM插件System.Security.Permissions.FileIOPermission错误
- 如何从Form2访问Form1函数而不创建新的Form();
- 键入initializer(静态构造函数)exception处理
- “null this”是否可以使用扩展方法?
- 有没有办法让OWIN托管SOAP服务?
- 在MySql.Data.dll中发生了MySql.Data.MySqlClient.MySqlException
- C#中大型列表如何使用可用内存?
- 与BeginGetRequestStream / EndGetRequestStream的TaskFactory.FromAsync挂起