C# SharpPcap 跨线程操作无效

发布于 2024-08-20 18:19:24 字数 5635 浏览 6 评论 0原文

您好,我正在尝试将 SharpPcap 新版本 SharpPcap-2.2.0rc1.src 中的示例 3 中的数据包捕获从控制台应用程序转换为 Windows 窗体应用程序。

当我尝试将已捕获的数据包添加到 ListView 控件时,我遇到一个问题,我会收到一个错误:

(跨线程操作无效:从创建它的线程以外的线程访问控制“listViewPackets”。)

在这一行:
listViewPackets.Items.Add(e.Packet.ToString());

任何解决此问题的建议???

这是我的代码:

using SharpPcap;

namespace Packets
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }



            // Retrieve the device list

        private void btnLiDevicest_Click(object sender, EventArgs e)
        {
            var devices = LivePcapDeviceList.Instance;
            // If no devices were found print an error
            if (devices.Count < 1)
            {
                MessageBox.Show("No devices were found on this machine");
                return;
            }


            int i = 0;

            // Print out the devices
            foreach (LivePcapDevice dev in devices)
            {

                ///* Description */
                //Console.WriteLine("{0}) {1} {2}", i, dev.Name, dev.Description);
                cmbListDevice.Items.Add(dev.Name + "   " + dev.Description);
                i++;
            }
           LivePcapDevice device = devices[1];
            // Register our handler function to the 'packet arrival' event
            device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);

            // Open the device for capturing
            int readTimeoutMilliseconds = 1000;
            device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
            device.StartCapture();


        }


            //Console.WriteLine();
            //Console.WriteLine("-- Listening on {0}, hit 'Enter' to stop...",
            //    device.Description);
                    /// <summary>
        /// Prints the time and length of each received packet
        /// </summary>
        /// 

        protected  void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            DateTime time = e.Packet.PcapHeader.Date;
            uint len = e.Packet.PcapHeader.PacketLength;
            //Console.WriteLine("{0}:{1}:{2},{3} Len={4}", 
            //    time.Hour, time.Minute, time.Second, time.Millisecond, len);

           // Console.WriteLine(e.Packet.ToString());

            listViewPackets.Items.Add(e.Packet.ToString());


        }



        }


}

................................................ ...................................... 这是原始代码:

using System;
using System.Collections.Generic;
using SharpPcap;
namespace SharpPcap.Test.Example3
{
    /// <summary>
    /// Basic capture example
    /// </summary>
    public class BasicCap
    {
        public static void Main(string[] args)
        {
            // Print SharpPcap version
            string ver = SharpPcap.Version.VersionString;
            Console.WriteLine("SharpPcap {0}, Example3.BasicCap.cs", ver);

            // Retrieve the device list
            var devices = LivePcapDeviceList.Instance;

            // If no devices were found print an error
            if(devices.Count < 1)
            {
                Console.WriteLine("No devices were found on this machine");
                return;
            }

            Console.WriteLine();
            Console.WriteLine("The following devices are available on this machine:");
            Console.WriteLine("----------------------------------------------------");
            Console.WriteLine();

            int i = 0;

            // Print out the devices
            foreach(LivePcapDevice dev in devices)
            {
                /* Description */
                Console.WriteLine("{0}) {1} {2}", i, dev.Name, dev.Description);
                i++;
            }

            Console.WriteLine();
            Console.Write("-- Please choose a device to capture: ");
            i = int.Parse( Console.ReadLine() );

            LivePcapDevice device = devices[i];

            // Register our handler function to the 'packet arrival' event
            device.OnPacketArrival += 
                new PacketArrivalEventHandler( device_OnPacketArrival );

            // Open the device for capturing
            int readTimeoutMilliseconds = 1000;
            device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

            Console.WriteLine();
            Console.WriteLine("-- Listening on {0}, hit 'Enter' to stop...",
                device.Description);

            // Start the capturing process
            device.StartCapture();

            // Wait for 'Enter' from the user.
            Console.ReadLine();

            // Stop the capturing process
            device.StopCapture();

            Console.WriteLine("-- Capture stopped.");

            // Print out the device statistics
            Console.WriteLine(device.Statistics().ToString());

            // Close the pcap device
            device.Close();
        }

        /// <summary>
        /// Prints the time and length of each received packet
        /// </summary>
        private static void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            DateTime time = e.Packet.PcapHeader.Date;
            uint len = e.Packet.PcapHeader.PacketLength;
            Console.WriteLine("{0}:{1}:{2},{3} Len={4}", 
                time.Hour, time.Minute, time.Second, time.Millisecond, len);
            Console.WriteLine(e.Packet.ToString());
        }
    }
}

Hi I'm trying to convert packet capturing in Example3 in SharpPcap new version SharpPcap-2.2.0rc1.src from Console Application to Windows Forms Application.

I'm facing a problem when I tried to add packets has been captured to ListView control I will get an error which is:

(Cross-thread operation not valid: Control 'listViewPackets' accessed from a thread other than the thread it was created on.)

at this line:
listViewPackets.Items.Add(e.Packet.ToString());

any Advice to solve this problem???

here is my code:

using SharpPcap;

namespace Packets
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }



            // Retrieve the device list

        private void btnLiDevicest_Click(object sender, EventArgs e)
        {
            var devices = LivePcapDeviceList.Instance;
            // If no devices were found print an error
            if (devices.Count < 1)
            {
                MessageBox.Show("No devices were found on this machine");
                return;
            }


            int i = 0;

            // Print out the devices
            foreach (LivePcapDevice dev in devices)
            {

                ///* Description */
                //Console.WriteLine("{0}) {1} {2}", i, dev.Name, dev.Description);
                cmbListDevice.Items.Add(dev.Name + "   " + dev.Description);
                i++;
            }
           LivePcapDevice device = devices[1];
            // Register our handler function to the 'packet arrival' event
            device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);

            // Open the device for capturing
            int readTimeoutMilliseconds = 1000;
            device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
            device.StartCapture();


        }


            //Console.WriteLine();
            //Console.WriteLine("-- Listening on {0}, hit 'Enter' to stop...",
            //    device.Description);
                    /// <summary>
        /// Prints the time and length of each received packet
        /// </summary>
        /// 

        protected  void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            DateTime time = e.Packet.PcapHeader.Date;
            uint len = e.Packet.PcapHeader.PacketLength;
            //Console.WriteLine("{0}:{1}:{2},{3} Len={4}", 
            //    time.Hour, time.Minute, time.Second, time.Millisecond, len);

           // Console.WriteLine(e.Packet.ToString());

            listViewPackets.Items.Add(e.Packet.ToString());


        }



        }


}

.................................
....................................
here is the original code:

using System;
using System.Collections.Generic;
using SharpPcap;
namespace SharpPcap.Test.Example3
{
    /// <summary>
    /// Basic capture example
    /// </summary>
    public class BasicCap
    {
        public static void Main(string[] args)
        {
            // Print SharpPcap version
            string ver = SharpPcap.Version.VersionString;
            Console.WriteLine("SharpPcap {0}, Example3.BasicCap.cs", ver);

            // Retrieve the device list
            var devices = LivePcapDeviceList.Instance;

            // If no devices were found print an error
            if(devices.Count < 1)
            {
                Console.WriteLine("No devices were found on this machine");
                return;
            }

            Console.WriteLine();
            Console.WriteLine("The following devices are available on this machine:");
            Console.WriteLine("----------------------------------------------------");
            Console.WriteLine();

            int i = 0;

            // Print out the devices
            foreach(LivePcapDevice dev in devices)
            {
                /* Description */
                Console.WriteLine("{0}) {1} {2}", i, dev.Name, dev.Description);
                i++;
            }

            Console.WriteLine();
            Console.Write("-- Please choose a device to capture: ");
            i = int.Parse( Console.ReadLine() );

            LivePcapDevice device = devices[i];

            // Register our handler function to the 'packet arrival' event
            device.OnPacketArrival += 
                new PacketArrivalEventHandler( device_OnPacketArrival );

            // Open the device for capturing
            int readTimeoutMilliseconds = 1000;
            device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

            Console.WriteLine();
            Console.WriteLine("-- Listening on {0}, hit 'Enter' to stop...",
                device.Description);

            // Start the capturing process
            device.StartCapture();

            // Wait for 'Enter' from the user.
            Console.ReadLine();

            // Stop the capturing process
            device.StopCapture();

            Console.WriteLine("-- Capture stopped.");

            // Print out the device statistics
            Console.WriteLine(device.Statistics().ToString());

            // Close the pcap device
            device.Close();
        }

        /// <summary>
        /// Prints the time and length of each received packet
        /// </summary>
        private static void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            DateTime time = e.Packet.PcapHeader.Date;
            uint len = e.Packet.PcapHeader.PacketLength;
            Console.WriteLine("{0}:{1}:{2},{3} Len={4}", 
                time.Hour, time.Minute, time.Second, time.Millisecond, len);
            Console.WriteLine(e.Packet.ToString());
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白况 2024-08-27 18:19:24

当从另一个线程调用控件时:

if (listView1.InvokeRequired)
{
    listView1.BeginInvoke(new MethodInvoker(
        () => /*whatever you want with listview */));
}
else
{
    /* whatever you want with listview */
}

如果您确定它将始终位于另一个线程上,那么只需忘记 if/else 并使用调用即可。

编辑:

所以在你的情况下,它看起来像:(

if(listView1.InvokeRequired)
{
    listView1.BeginInvoke(new MethodInvoker(
        () => listViewPackets.Items.Add(e.Packet.ToString()) ));
}
else
{
    listViewPackets.Items.Add(e.Packet.ToString());
}

再次,或者只是 BeginInvoke 调用,如果它总是在不同的线程上运行)

编辑2
您会注意到 Shane 使用 Invoke,而我使用 BeginInvoke。我把它当作一种习惯的力量。使用 Invoke 将阻塞 UI 线程,如果您执行的操作需要更长时间,则使用 BeginInvoke 会异步执行 UI 更新。

When making a call to a control from another thread:

if (listView1.InvokeRequired)
{
    listView1.BeginInvoke(new MethodInvoker(
        () => /*whatever you want with listview */));
}
else
{
    /* whatever you want with listview */
}

If you know for sure that it will always be on another thread, then just forget the if/else and use the invoke.

EDIT:

so in your case, it'd look like:

if(listView1.InvokeRequired)
{
    listView1.BeginInvoke(new MethodInvoker(
        () => listViewPackets.Items.Add(e.Packet.ToString()) ));
}
else
{
    listViewPackets.Items.Add(e.Packet.ToString());
}

(again, or just the BeginInvoke call, if it will always run on a different thread)

EDIT 2
You'll notice that Shane uses Invoke and I use BeginInvoke. I use it as a force of habit. Using Invoke will block on the UI thread, and if you're performing an operation that takes longer, using BeginInvoke performs the update to the UI asynchronously.

寄离 2024-08-27 18:19:24

您需要使用 Invoke 因为数据包来自不同的线程。 UI 控件无法在创建它们的线程以外的线程上进行修改。 Invoke 将在 UI 线程上执行给定的委托。例如,您可以这样做:

this.Invoke(new MethodInvoker(() => listViewPackets.Items.Add(e.Packet.ToString())), null);

You need to use Invoke because the packet is coming in on a different thread. UI controls cannot be modified on a thread other than the one they're created on. Invoke will execute the given delegate on the UI thread. For example, you could do this:

this.Invoke(new MethodInvoker(() => listViewPackets.Items.Add(e.Packet.ToString())), null);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文