C# WPF 代码在 Visual Studio 中的运行速度比在控制台中的运行速度快,而在另一个文件夹中的运行速度较慢

标签 c# wpf performance visual-studio

这是我见过的最奇怪的问题,我希望你觉得它有趣。我创建了一个 C# WPF 示例,它作为典型的数据包嗅探器(来源如下)监听 IP 数据包,并将一些数据打印到屏幕上。我有非常一致和可重复的行为,但有两个结果(快和慢)。

先决条件:由于 IP 套接字代码,以管理员身份运行 Visual Studio 2010。

如果我在 Visual Studio 中以 x86 Release模式运行应用程序(单击绿色箭头),它每秒处理大约 300 个数据包(快速)。完美的。如果我在 Debug模式下运行它,它每秒处理大约 1 个数据包(慢)。这是可以理解的,因为 Debug模式会增加开销。但是,等等,这就是奇怪的地方。

问题/疑问:

  1. 如果我将解决方案复制到另一个文件夹并从 Visual Studio 中运行(与以前一样的 x86 版本),它运行缓慢。但是,如果我将相同的解决方案复制回原始文件夹路径,它运行得很快。为什么?

  2. 如果我从命令提示符以管理员身份运行 x86 Release模式可执行文件,它每秒处理大约 1 个(慢)。为什么? (编辑:这可能是因为 VS 托管过程带来的任何性能提升在 VS 之外都不存在。)

因此,代码只有在原始文件夹中从 Visual Studio(x86 版本)运行时才能快速执行。

我尝试过的其他事情:

  1. 清理并手动修改 obj 和 bin 文件夹...并重建解决方案。
  2. 清理注册表并删除所有引用应用程序或路径的行。
  3. 删除了 Windows 防火墙中引用该应用程序名称的所有条目。
  4. 禁用防病毒软件并将该应用程序添加到排除列表。
  5. 运行 Visual Studio 输出文本的差异比较 (BeyondCompare)。
  6. 创建了新的解决方案并将代码复制/粘贴到其中,如果名称不同或不在同一文件夹中,它们仍然运行缓慢。
  7. 与每秒显示大约 300 个数据包的 WireShark 捕获相比。
  8. 启用/禁用 VS 主机进程。如果解决方案仅在原始路径中,则启用运行速度更快。
  9. 重新启动

MainWindow.xaml

   <Window x:Class="WpfSingle.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525" Closing="Window_Closing">
        <Grid>
            <ScrollViewer>
                <TextBlock Name="textBlock1"></TextBlock>
            </ScrollViewer>
        </Grid>
    </Window>

MainWindow.xaml.cs

using System;
using System.Text;
using System.Windows;
using System.Net.Sockets;
using System.Net;

namespace WpfSingle
    {
        public partial class MainWindow : Window
        {
            private static System.Threading.Thread _processingThread;
            private bool _killThread;
            private Socket _socket;
            private const int PACKET_MAX_SIZE = 32768;
            private byte[] _bytesIn;
            private byte[] _bytesOut;
            private byte[] _byteData;
            private int _bytesReceived;
            private int _packetCounter;
            private string Interface = "192.168.1.42";
            private StringBuilder _sbTextOut;

            public MainWindow()
            {
                InitializeComponent();
                _sbTextOut = new StringBuilder();

                try
                {
                    _processingThread = new System.Threading.Thread(ThreadProcess);
                    _processingThread.Start();
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }

            private void ThreadProcess()
            {
                _killThread = false;
                _byteData = new byte[PACKET_MAX_SIZE];
                _bytesIn = new byte[4] { 1, 0, 0, 0 };
                _bytesOut = new byte[4] { 1, 0, 0, 0 };
                _packetCounter = 0;

                try
                {
                    _socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
                    _socket.Bind(new IPEndPoint(IPAddress.Parse(Interface), 0));
                    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
                    _socket.IOControl(IOControlCode.ReceiveAll, _bytesIn, _bytesOut);
                }
                catch (Exception ex)
                {
                    if (_socket != null) _socket.Close();
                    Console.Error.WriteLine(ex.Message);
                }

                while (true)
                {
                    OnThreadProcess();
                    if (_killThread)
                        break;
                }
            }

            private void OnThreadProcess()
            {
                if (_socket != null)
                {
                    EndPoint ep = new IPEndPoint(IPAddress.Any, 0) as EndPoint;
                    try
                    {
                        _bytesReceived = _socket.ReceiveFrom(_byteData, _byteData.Length, SocketFlags.None, ref ep);
                        if (_bytesReceived > 0)
                        {
                            _packetCounter++;
                            if (_packetCounter >= 300) _killThread = true;

                            _sbTextOut.AppendLine(string.Format("{0} : {1} {2} {3} {4} {5} {6} {7}", DateTime.Now.ToString("H:mm:ss.ffffff"), _packetCounter, _byteData[0], _byteData[1], _byteData[2], _byteData[3], _byteData[4], _byteData[5]));
                            Dispatcher.Invoke(new Action(() =>
                            {
                                textBlock1.Text = _sbTextOut.ToString(); 
                            }));
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Error.WriteLine(ex.Message);
                    }
                }
            }

            private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                _killThread = true;
            }
        }
    }

最佳答案

不幸的是,代码现在在所有配置中都以很慢的速度捕获。我无法再获得 300/秒的数据包捕获。它现在正在运行/捕获大约 2-3/秒。是的,我使用的是相同的源代码。我确信问题与 vshosts 有关(感谢 Kris)。不幸的是,我仍然不知道如何重新创建更高的捕获率,而较慢的捕获率也不够好用。显然这是可能的,因为它整天都在快速运行……直到现在。感谢大家的帮助。

关于C# WPF 代码在 Visual Studio 中的运行速度比在控制台中的运行速度快,而在另一个文件夹中的运行速度较慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26680486/

相关文章:

sql - 相似度匹配算法

c# - 在 C# 中,显示可缩放和平移视频的好方法是什么?

c# - 尝试使用 Entity Framework Code First 更新数据库

基于数据类型的WPF设置样式?

c# - 如何在我的 ViewModel 中监听来自另一个 ViewModel 的更改?

c# - 当鼠标悬停在按钮WPF上时,如何制作更改图像的图像按钮?

java - 为什么 haskell 的性能比 java 差

SQL 比较两个日期的最快方法(非标准 varchar 格式和日期时间)

c# - 具有相同类型的嵌套 Dto 的 Dto 失败

c# - ExecuteScalar 找不到存储过程