请教一个ArrayList加锁的问题

gxingmin 2016-04-07 03:20:27
需求是这样的,批量发送邮件:
选一批接收人,点击发送邮件,把这批人加到代发数组里(array),开启线程开始发送,发一封从array里remove掉一个,
如果此时代发还没发完,这时又选一批接收人,点击发送邮件,要把这次选的人加到刚才的代发数组里继续发送

代码如下:
private void btnSend_click(){	
lock(arryList.SyncRoot)
{
foreach(string strGroup in OneLstGroup.Items)
{

poLedInfo []pos = m_boLedInfo.GetInfoByGroupName(strGroup);

foreach(poLedInfo po in pos)
{
//SendToSingleMemeber(po,/*po.Name+":"+*/strContent);
arryList.Add(new ListItem(strContent, po));
}
}
}

if(!m_bSending) //开启线程发送
{

Thread t = new Thread(new ThreadStart(SendFunc));
t.Start();
}
}

//发送线程
private void SendFunc()
{
m_bSending = true; //正在发送

lock(arryList.SyncRoot)
{
while(arryList.Count > 0)
{
Console.WriteLine("----------------{0}", arryList.Count);
ListItem lst = (ListItem)arryList[0];
poLedInfo po = lst.Value as poLedInfo;
SendToSingleMemeber(po, lst.Name);

arryList.RemoveAt(0);

Thread.Sleep(10);
}
}

Console.WriteLine("''''''----------------{0}", arryList.Count);

m_bSending = false;
}



现在遇到问题了,第一次点button后进线程发送,第二次再点(第一次线程还没发完),程序就挂了,貌似死锁了
估计是锁用的不对,哪位大神帮忙看下怎么改?谢谢
...全文
316 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
zj_zwl 2016-04-08
  • 打赏
  • 举报
回复
4楼的做法可以
秋的红果实 2016-04-08
  • 打赏
  • 举报
回复
去掉锁,用公共变量m_bSending控制,每次点击按钮,先停止邮件发送,添加新邮件到列表后,再开始发送邮件

public bool isFinished=false; //当前发送的邮件完成是否完成
private void btnSend_click(){	
                             // lock(arryList.SyncRoot)
					//{
                                                m_bSending=false;  //计划停止发送
                                                while(!isFinished)
                                                {
                                                   System.Threading.Thread.Sleep(30000); //给足够时间让当前发送邮件完成
                                                }

                                                //假设你下面的代码是在添加新邮件到列表
						foreach(string strGroup in OneLstGroup.Items)
						{
							
							poLedInfo []pos = m_boLedInfo.GetInfoByGroupName(strGroup);
				
							foreach(poLedInfo po in pos)
							{			
								//SendToSingleMemeber(po,/*po.Name+":"+*/strContent);
								arryList.Add(new ListItem(strContent, po));
							}
						}
					//}

                                  if(!m_bSending) //开启线程发送
			        {

				Thread t = new Thread(new ThreadStart(SendFunc));
				t.Start();
			     }
}

//发送线程
private void SendFunc()
		{
			m_bSending = true;  //正在发送

			//lock(arryList.SyncRoot)
			//{
				while(arryList.Count > 0 && m_bSending )
				{
                                        isFinished=false;

					Console.WriteLine("----------------{0}", arryList.Count);
					ListItem lst = (ListItem)arryList[0];
					poLedInfo po = lst.Value as poLedInfo;
					SendToSingleMemeber(po, lst.Name);

					arryList.RemoveAt(0);

					Thread.Sleep(10);

                                         isFinished=true;
				}
			//}

			Console.WriteLine("''''''----------------{0}", arryList.Count);

			m_bSending = false;
		}
threenewbee 2016-04-07
  • 打赏
  • 举报
回复
http://blog.csdn.net/wangzhiyu1980/article/details/45497907
秋的红果实 2016-04-07
  • 打赏
  • 举报
回复
你这么写,只有第一次点击的所有邮件发送完,才能添加本次新增的列表
qbilbo 2016-04-07
  • 打赏
  • 举报
回复
用Queue<ListItem>代替Array就不用锁了。
xian_wwq 2016-04-07
  • 打赏
  • 举报
回复
引用 楼主 gxingmin 的回复:
需求是这样的,批量发送邮件: 选一批接收人,点击发送邮件,把这批人加到代发数组里(array),开启线程开始发送,发一封从array里remove掉一个, 如果此时代发还没发完,这时又选一批接收人,点击发送邮件,要把这次选的人加到刚才的代发数组里继续发送 代码如下:
private void btnSend_click(){	
                              lock(arryList.SyncRoot)
					{
						foreach(string strGroup in OneLstGroup.Items)
						{
							
							poLedInfo []pos = m_boLedInfo.GetInfoByGroupName(strGroup);
				
							foreach(poLedInfo po in pos)
							{			
								//SendToSingleMemeber(po,/*po.Name+":"+*/strContent);
								arryList.Add(new ListItem(strContent, po));
							}
						}
					}

                                  if(!m_bSending) //开启线程发送
			        {

				Thread t = new Thread(new ThreadStart(SendFunc));
				t.Start();
			     }
}

//发送线程
private void SendFunc()
		{
			m_bSending = true;  //正在发送

			lock(arryList.SyncRoot)
			{
				while(arryList.Count > 0)
				{
					Console.WriteLine("----------------{0}", arryList.Count);
					ListItem lst = (ListItem)arryList[0];
					poLedInfo po = lst.Value as poLedInfo;
					SendToSingleMemeber(po, lst.Name);

					arryList.RemoveAt(0);

					Thread.Sleep(10);
				}
			}

			Console.WriteLine("''''''----------------{0}", arryList.Count);

			m_bSending = false;
		}
现在遇到问题了,第一次点button后进线程发送,第二次再点(第一次线程还没发完),程序就挂了,貌似死锁了 估计是锁用的不对,哪位大神帮忙看下怎么改?谢谢
为何解析的时候要不停的起新的线程呢? 消费者线程起一个就够了。 个人理解: 运行时间段-线程池,时间长-单独线程。
我是飞云 2016-04-07
  • 打赏
  • 举报
回复
arryList.SyncRoot 这个是静态吧? 为什么不在当前类定义个变量呢?
Poopaye 2016-04-07
  • 打赏
  • 举报
回复
楼主你的号是从别人手里买来的吗?

110,557

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧