先上我接收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,可能没写对,数据还是不全。
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,可能没写对,数据还是不全。
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 );
}
}
}
}
}