先上我接收UDP的代码,问题在后面
        private void button31_Click(object sender, RoutedEventArgs e)
        {
            thread1 = new Thread(Acc);
            thread1.Start();
            button31.IsEnabled = false;
        }     private void Acc()
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Any, 8899);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);   //绑定已使用端口 (也许是程序死机前用的端口)
            socket.Bind(iep);
            ep = (EndPoint)iep;
            byte[] bytes = new byte[1024];//设置缓冲数据流长度是1024            while (true)
            {
                string receiveData;
                socket.ReceiveFrom(bytes, ref ep);
                receiveData = System.Text.Encoding.Unicode.GetString(bytes);
                receiveData = receiveData.TrimEnd('\u0000');
                if (receiveData.Length > 0)
                {
                    //textBox1.Text = "来自" + ep.ToString() + "的消息" + receiveData;
                    TextBoxCallback tx = SetTextBox;
                    this.Dispatcher.Invoke(tx, receiveData);
                    Array.Clear(bytes, 0, 1024);//数组初清零
                }
            }
        }       delegate void TextBoxCallback(string str);//是接收来网络K发射机传来的文本
        ArrayList uiyi = new ArrayList();//用来存接收数据        public void SetTextBox(string str)
        {
            uiyi.Add(str);
        }我用上面的代码来接收UDP数据,我UDP发射端每秒最多发射120次,也就是发射120行数据,我这里接收用"SetTextBox"方法,将数据直接放入ArrayList数组,测试很长时间,ArrayList uiyi 都能收到全部发射数据。但我的数据要分析处理,我就在“public void SetTextBox”直接进行对数据的加减乘除,在发射端时间间隔一样时,每秒120次的数据量时,对数据的加减乘除处理都未影响接收UDP数据。但实际工作中发射端发射数据一时多,一时少,但都没有超过每秒120次,这时数据处理就影响我的接收了,数据收不全了。如将数据放入ArrayList中,数据是全部收到的。 
我想问的是:有什么方法能将接收到的UDP数据缓存一下,再对数据进行加减乘除。我用过生产者消费者模式的lock,可能没写对,数据还是不全。

解决方案 »

  1.   

    生产者消费者模式是可以的,很简单,用ArrayList不是很好,缓冲的数据最好存在队列里,队列最好是用LinkedList实现比较容易操作,生产者和消费者都直接lock(LinkedList),然后生产者接收到数据后,往LinkedList末尾添加,而消费者,处理数据的程序则从LinkedList开头取数据处理,完之后删除这个数据,这样一直到LinkedList为空为止,
      

  2.   

    因为在单位时间内我的数据接收的量基本上是小于我分析处理量,只在很短很短时间内,接收量是大于分析处理量。是不是因为生产者消费者模式的lock上锁,影响了我的数据接收。用Queen能否解决这个问题?
      

  3.   

    引用其它文章
    Queue与线程的应用 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Threading; namespace 集合 

        class 队列 
        { 
            public static void Main() 
            {  
                //队列: 元素以先进先出的方式来处理的集合(FIFO-First In First Out)第一个来,第一个滚 
                //例:飞机登记排队,靠前的就先上飞要,不过队列有优先级,如商务仓的队与经济仓的队,是两个不同的队,而商务优先 
                //在.Net技术中,      using System.Collections.Generic.Queue<T>是队列的泛型版本实现 
                // System.Collections.Queue是非泛型的实现,参数是Object 
                //public class Queue<T> : IEnumerable<T>, ICollection, IEnumerable 
                //从队列的定义可以看出,它实现了跌代,集合接口 ,它没有实现ICollection<T>这个接口,因为其中定义的Add Remove方法会破坏队列 
                //队列与列表主要区别就是在于,它没有实现IList接口 
                //所以,不可以用索引器访问队列,队列只允许添加元素,该元素只能放在队列的最后(Enqueue()),还有就是从头部取元素Dequeue() 
                //Enqueue从队列的后面插入元素,而 Dequeue在取一个元素的同时,会前取出的元素删除,如再再调用一次,就删除下一个元素 
                 
                //方法简介 : 
                // Enqueue() 一端插入元素 
                // Dequeue() 从头部读取和删除一个元素,如果调用方法时,队列中没有元素,刨出InvalidOperationException异常 
                // Peek() 在队列头部读取一个元素,但是,不删除它 
                // Count 返回队列元素个数 
                // TrimExcess() 重新设置队列容量,Dequeue方法,是可能删除一个对象,但是,不会重设容量,这样会浪费空余空间 ,本方法,从头部清除空余空间 
                // Contains() 确定某个元素是不是在队列中,如果是,返回true 
                // CopyTo() 把元素从队列复制到一个已有的数组中  
                // ToArray() 返回一个包含队列元素的新数组             // 下面我们开始写一个关于队列的例子, 使用一个线程将文档添加到队列中,用另一个线程读取队列,并处理他们 
                // 存储队列的类型是Document,我们先定义一个文档类,接着定义一个文档处理类DocumentManager,其中包含了添加与读取方法,还有一个属性确定队列中是不是为空 
                // 然后我们定义一个 ProcessDocuments来处理线程,操作文档 
                
                DocumentManager mg = new DocumentManager(); 
                ProcessDocuments prcess = new ProcessDocuments( mg ); 
                //启动读取线程,不过现在没内容,要等一会加入后,就能读到了 
                ProcessDocuments.Start(mg);             Document doc = null;             for (int i = 0; i < 500; i++) 
                { 
                    doc = new Document("Aladdin:" + i, "Hello,Nihao!"); 
                    mg.AddDocument( doc ); 
                    //睡会,让给其他线程玩会 
                    //Thread.Sleep(20); 
                }             Console.ReadLine(); 
            } 
        } 
         
        // 文档类,描述了文档的标题与内容 
        class Document 
        { 
            public string title; 
            public string content;         public Document(string title, string content) 
            { 
                this.title = title; 
                this.content = content; 
            } 
        }     class DocumentManager 
        { 
            //定义队列集合 
            private readonly Queue<Document> docQueue = new Queue<Document>(); 
             
            //添加文档 
            public void AddDocument(Document doc) 
            { 
                lock (this) 
                { 
                    //从队列一端插入内容 
                    docQueue.Enqueue(doc); 
                    Console.WriteLine( "成功插入文档:" + doc.title); 
                } 
            } 
             
            //读取文档 
            public Document GetDocument() 
            { 
                Document doc = null;             lock (this) 
                { 
                    doc = docQueue.Dequeue(); 
                    return doc; 
                } 
            }         //只读属性,确定队列中是不是还有元素 
            public bool IsDocumentAvailable 
            { 
                get 
                { 
                    return docQueue.Count > 0; 
                } 
            } 
        }     // 处理文档 
        class ProcessDocuments 
        { 
            private DocumentManager dm;         public ProcessDocuments( DocumentManager dm ) 
            { 
                this.dm = dm; 
            }         public static void Start(DocumentManager manager) 
            {  
                // 参数 : public delegate void ThreadStart(); 
                new Thread(new ProcessDocuments(manager).DoThreadFunc).Start() ; 
            }         public void DoThreadFunc() 
            {  
                //无限循环读取,只要队列中有内容,这条线程就读出来             while (true) 
                { 
                    if (this.dm.IsDocumentAvailable) 
                    { 
                        Document doc = this.dm.GetDocument() ; 
                        Console.WriteLine("从队列中读到读取并删除文档 标题:{0}   内容: {1}", doc.title, doc.content ); 
                    } 
                } 
            } 
        } 
    }