C# 通知自己/创建线程上的事件订阅者
我有一个名为C# 通知自己/创建线程上的事件订阅者,c#,.net,multithreading,event-handling,C#,.net,Multithreading,Event Handling,我有一个名为DirectoryCopier的类,它公开了进程事件,在该事件中,我的windows窗体对象将订阅此事件,然后调用CopyFolderAsync开始在不同线程上复制和通知事件处理程序 class DirectoryCopier { public event EventHandler<CopyProgressChangedEventArgs> CopyProgressChanged; public void CopyFolderAsync() {
DirectoryCopier
的类,它公开了进程事件,在该事件中,我的windows窗体对象将订阅此事件,然后调用CopyFolderAsync开始在不同线程上复制和通知事件处理程序
class DirectoryCopier
{
public event EventHandler<CopyProgressChangedEventArgs> CopyProgressChanged;
public void CopyFolderAsync()
{
Task.Run(() => CopyFolder(Source, Destination));
}
void CopyFolder(string src, string des)
{
string srcName = Path.GetFileName(src);
string desDir = Path.Combine(des, srcName);
Directory.CreateDirectory(desDir);
var files = Directory.EnumerateFiles(src);
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string desFile = Path.Combine(desDir, fileName);
CopyFile(file, desFile);
}
var dirs = Directory.EnumerateDirectories(src);
foreach (string dir in dirs)
CopyFolder(dir, desDir);
}
void CopyFile(string src, string dest)
{
using (FileStream input = new FileStream(src, FileMode.Open, FileAccess.Read, FileShare.None, buffer.Length))
using (FileStream output = new FileStream(dest, FileMode.Create, FileAccess.Write, FileShare.None, buffer.Length))
{
byte[] buffer = new byte[1024 * 1024];
int bytesRead;
do
{
bytesRead = input.Read(buffer, 0, buffer.Length);
output.Write(buffer, 0, bytesRead);
if (CopyProgressChanged != null)
CopyProgressChanged.BeginInvoke(this, new CopyProgressChangedEventArgs(,,,),null,null);
}
while (bytesRead > 0);
}
}
}
调试我的应用程序时,progressbar值会正常更新,但在我的表单中不是高级的,IntelliTrace窗格中捕获了许多跨线程异常。我可以使用Form.Invoke()更新progressBar,但这是事件处理程序的责任吗?有什么方法可以调用他自己/创建线程上的每个订阅服务器吗?问题不是调用他创建线程上的每个订阅服务器,而是绑定到UI线程的UI控件 我发现了一个很好的扩展方法,它尝试为每个代理提取
SynchronizationContext
。如果存在委托,它将使用BeginInvoke
:
public static object Raise(this MulticastDelegate
多播代理、对象发送方、事件参数(e)
{
object retVal=null
MulticastDelegate threadSafeMulticastDelegate = multicastDelegate;
if (threadSafeMulticastDelegate != null)
{
foreach (Delegate d in threadSafeMulticastDelegate.GetInvocationList())
{
var synchronizeInvoke = d.Target as ISynchronizeInvoke;
if ((synchronizeInvoke != null) && synchronizeInvoke.InvokeRequired)
{
retVal = synchronizeInvoke.EndInvoke(synchronizeInvoke.BeginInvoke(d, new[] { sender, e }));
}
else
{
retVal = d.DynamicInvoke(new[] { sender, e });
}
}
}
return retVal;
}
}
您可以将其用于以下活动:
MyEvent.Raise(sender, eventArgs);
MyEvent.Raise(sender, eventArgs);