c# - 如果我多次复制,WM_DRAWCLIPBOARD 和 WM_CHANGECBCHAIN 会占用大量内存。在我的程序 C#
问题描述
我使用剪贴板监视器。正因为如此,我注意到 wndproc 是内存泄漏,而没有放下垃圾收集。但是提到如果我复制某些内容,我需要更多的 CPU 来替代此代码以减少内存使用量?
我希望复制内存使用量不要太多,除了使用垃圾收集还有另一种选择吗?
这是我的代码。
[DefaultEvent(nameof(ClipboardChanged))]
public sealed class ClipboardMonitor : Control, IEquatable<ClipboardMonitor>
{
private IntPtr nextClipboardViewer;
public ClipboardMonitor()
{
BackColor = Color.Red;
Visible = false;
nextClipboardViewer = (IntPtr)SetClipboardViewer((int)Handle);
}
/// <summary>
/// Clipboard contents changed.
/// </summary>
public event EventHandler<ClipboardChangedEventArgs> ClipboardChanged;
protected override void Dispose(bool disposing)
{
try
{
_ = ChangeClipboardChain(Handle, nextClipboardViewer);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
base.Dispose(disposing);
}
protected override void WndProc(ref Message m)
{
// defined in winuser.h
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
switch (m.Msg)
{
case WM_DRAWCLIPBOARD:
{
OnClipboardChanged();
_ = SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
break;
}
case WM_CHANGECBCHAIN:
{
if (m.WParam == nextClipboardViewer)
{
nextClipboardViewer = m.LParam;
}
else
{
_ = SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
break;
}
default:
{
base.WndProc(ref m);
break;
}
}
}
[DllImport("User32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
private static extern int SetClipboardViewer(int hWndNewViewer);
private void OnClipboardChanged()
{
try
{
IDataObject iData = Clipboard.GetDataObject();
ClipboardChanged?.Invoke(this, new ClipboardChangedEventArgs(iData));
}
catch (Exception e)
{
_ = MessageBox.Show(e.ToString());
}
}
public bool Equals(ClipboardMonitor other)
{
throw new NotImplementedException();
}
}
public sealed class ClipboardChangedEventArgs : EventArgs
{
internal readonly IDataObject DataObject;
internal ClipboardChangedEventArgs(IDataObject dataObject = null)
{
if (dataObject is null)
{
throw new ArgumentNullException(nameof(dataObject));
}
DataObject = dataObject;
}
}
这是我现在的 wndproc 代码
protected override void WndProc(ref Message m)
{
// defined in winuser.h
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
switch (m.Msg)
{
case WM_DRAWCLIPBOARD:
{
OnClipboardChanged();
_ = SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
break;
}
case WM_CHANGECBCHAIN:
{
if (m.WParam == nextClipboardViewer)
{
nextClipboardViewer = m.LParam;
}
else
{
_ = SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
break;
}
default:
{
base.WndProc(ref m);
break;
}
}
}
让我知道我可以对这段代码进行哪些改进。
解决方案
推荐阅读
- filter - 在 Tableau 中过滤掉所有行时显示零
- angular - 角度分组和合并数组
- python-3.x - Python,Selenium:单击 for 循环中的下一个链接?
- python - itertools count() 使用多处理池重置
- react-native - React Native - 使用带有 render() 的钩子
- django - 如何在同一个端口上设置 Django 和 React 并处理路由?
- amazon-web-services - SSH 进入私有 VPC 子网
- laravel - Laravel Collection groupBy 在第二个分组中对一个元素进行多重和平均
- bash - Bash从自定义字符串日期获取纪元时间
- python - 将 mutt 用于 .csv 文件时,增加了一行