gpt4 book ai didi

c# - 在自己的/创建线程上通知事件订阅者

转载 作者:太空宇宙 更新时间:2023-11-03 13:18:07 25 4
gpt4 key购买 nike

我有一个名为 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);
}
}
}

在我的表单的事件处理程序中,我确实使用接收到的事件参数更新进度条,这在我运行时工作正常。

        progressBar1.Value = e.ProgressPercentage;

当我调试我的应用程序时,进度条值正常更新但在我的表单中没有提前,并且许多跨线程异常已在 IntelliTrace Pane 中捕获。我可以使用 Form.Invoke() 来更新 progressBar 但这是事件处理程序的责任吗?有没有办法在他自己的/创建线程上调用每个订阅者?

最佳答案

问题不在于在他的创建线程上调用每个订阅者,特别是绑定(bind)到 UI 线程的 UI 控件。

我找到了一个不错的扩展方法 here它尝试为每个委托(delegate)提取 SynchronizationContext。如果存在,它将使用 BeginInvoke 调用其上的委托(delegate):

public static object Raise(this MulticastDelegate 

multicastDelegate, object sender, EventArgs e) { 对象 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);

关于c# - 在自己的/创建线程上通知事件订阅者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25344631/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com