문제

안녕하세요 샤프 캡에서 example3에서 패킷 캡처를 변환하려고합니다. 새 버전 SharpPCap-2.2.0rc1.src에서 콘솔 응용 프로그램에서 Windows Forms 응용 프로그램으로.

패킷을 추가하려고 할 때 문제에 직면 해 있습니다. ListView Control에 캡처되었을 때 다음과 같은 오류가 발생합니다.

(크로스 스레드 작업 유효하지 않음 : 제어 '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());
        }
    }
}
도움이 되었습니까?

해결책

다른 스레드에서 컨트롤을 호출 할 때 :

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());
}

(다시, 또는 항상 다른 스레드에서 실행되는 경우, Beartinvoke 호출만으로)

편집 2 Shane은 Invoke를 사용하고 BeginInvoke를 사용한다는 것을 알 수 있습니다. 나는 그것을 습관의 힘으로 사용합니다. invoke를 사용하면 UI 스레드가 차단되며, 더 오래 걸리는 작업을 수행하는 경우 BeginInvoke를 사용하면 UI를 비동기로 업데이트합니다.

다른 팁

사용해야합니다 부르다 패킷이 다른 스레드에 들어 오기 때문에. UI 컨트롤은 생성 된 것 이외의 스레드에서 수정할 수 없습니다. Invoke는 UI 스레드에서 주어진 대의원을 실행합니다. 예를 들어,이를 수행 할 수 있습니다.

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top