我对.NET(C#)中的事件有疑问。我不得不为我运行后台任务的几种情况编写代码,我想通知主线程或控制器类发生了什么事情,例如任务完成,或者完成复制文件,但我不知道我希望后台任务等待主线程的委托处理事件。
我想做一些像消息传递这样的事情:发送消息,但是谁在乎他们用它做什么。
例如:
编写一个类来按顺序处理多个进程,一个接一个。每个进程都需要在后台线程上运行。当工作完成时,一个事件触发并告诉控制器它已完成(假设使用OnCompleted()方法)
问题在于,如果控制器的事件处理程序用于启动后续进程,则先前进程的OnComplete方法将保留在调用堆栈上(永远不会执行),直到所有进程都完成为止。
在那种情况下,后台任务如何通知控制器类工作完成而不保留事件提升方法?
示例2:备份程序。
后台线程运行以将每个文件复制到目标。后台需要通知 UI最后复制的文件,但不需要等待UI更新。相反,它只是想说,“顺便说一下,这里有一些信息。现在,让我重新开始工作。”事件监听器不应阻止事件提升者的处理。
答案 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编码的不同技术